content: /*
   *  Copyright Beijing 58 Information Technology Co.,Ltd.
   *
   *  Licensed to the Apache Software Foundation (ASF) under one
   *  or more contributor license agreements.  See the NOTICE file
   *  distributed with this work for additional information
   *  regarding copyright ownership.  The ASF licenses this file
   *  to you 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.bj58.spat.gaea.server.bootstrap.serverframe;
  
  import java.awt.event.MouseAdapter;
  import java.awt.event.MouseEvent;
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  import javax.swing.JTree;
  import javax.swing.tree.DefaultTreeModel;
  import javax.swing.tree.TreePath;
  import javax.swing.tree.TreeSelectionModel;
  
  import com.bj58.spat.gaea.server.contract.annotation.OperationContract;
  import com.bj58.spat.gaea.server.contract.annotation.ServiceBehavior;
  import com.bj58.spat.gaea.server.contract.annotation.ServiceContract;
  import com.bj58.spat.gaea.server.contract.log.ILog;
  import com.bj58.spat.gaea.server.contract.log.LogFactory;
  import com.bj58.spat.gaea.server.deploy.hotdeploy.DynamicClassLoader;
  import com.bj58.spat.gaea.server.util.ClassHelper;
  
  /**
   * CheckNode
   * 
   * @author Service Platform Architecture Team (spat@58.com)
   */
  public class TreeFrame {
  	private static ILog logger = LogFactory.getLogger(TreeFrame.class);
  	/**
  	 * Tree选中记录
  	 */
  	private static Set<TreePath> checkedPathsSet =  new HashSet<TreePath>();
  	
  	public static TreeFrame create() {
  		return new TreeFrame();
  	}
  	/**build tree*/
  	public JTree buildTree() {
  		JTree tree = null;
  		/**load file jar and class*/
  		DynamicClassLoader classLoader = new DynamicClassLoader();
  		try {
  			classLoader.addFolder(AssistUtils.getPath());
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		logger.info("-----------------build Tree Start------------------");
  		
  		CheckNode parnodes = new CheckNode("method");
  		tree = new JTree(parnodes);
  		
  		List<String> jarList = classLoader.getJarList();
  		if(jarList!=null && jarList.size()>0){
  			loadClassTreeList(jarList,parnodes,classLoader);
  		}
  		
  		tree.setCellRenderer(new CheckRenderer());
  		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
  		tree.addMouseListener(new NodeSelectionListener(tree));
  		
  		logger.info("-----------------build Tree End--------------------");
  		return tree;
  	}
  	
  	/**
  	 * 根据jar文件中所包含类、方法生成具体树
  	 * @param jarList{jar list集合}
  	 * @param node 父节点
  	 * @param classLoader
  	 */
  	private static void loadClassTreeList(List<String> jarList,CheckNode node,DynamicClassLoader classLoader){
  		for(String ju:jarList){
  			if(ju!=null){
  				loadClassTreeServiceBehavior(ju,node,classLoader);
  			}
  		}
  	}
  	
  	/**
  	 * 根据jar文件中所包含类、方法生成具体树
  	 * @param jarUrl jar路径{ex:e:\a.jar}
  	 * @param node node父节点
  	 * @param classLoader
  	 */
  	private static void loadClassTreeServiceContract(String jarUrl,CheckNode node,DynamicClassLoader classLoader){
  		try{
  			Set<Class<?>> clsSet = ClassHelper.getClassFromJar(jarUrl, classLoader);
  			for(Class<?> cls : clsSet) {
  				
  				//ServiceContract contract = cls.getAnnotation(ServiceContract.class);
  				//如果存在ServiceContract的注解则添加
  				if(cls.getAnnotation(ServiceContract.class) != null){//定义接口
  					CheckNode classnodes = new CheckNode(cls.getName());//类名
  					node.add(classnodes);
  					Method [] methods = cls.getMethods();/**当前类包含方法*/
  					if(methods != null){
  						for(Method m : methods){
  							if(m.getAnnotation(OperationContract.class)!=null){
  								Class<?> methodParameter[] = m.getParameterTypes();/**该方法包含参数*/
  								String methodParameterStr = m.getName();
  								StringBuffer sbuffer = new StringBuffer();
  								if(methodParameter!=null){
  									for(int j=0,len=methodParameter.length;j<len;j++){
  										sbuffer.append(methodParameter[j].getName());
  										if(j < len-1){
  											sbuffer.append(",");
  										}
  									}	
  								}
  								if(sbuffer!=null){
  									methodParameterStr = methodParameterStr+"("+sbuffer.toString()+")";
  								}
  								CheckNode methodnodes = new CheckNode(methodParameterStr);
  								classnodes.add(methodnodes);
  								methodnodes = null;
  								methodParameterStr = null;
  								sbuffer = null;
  							}
  						}
  					}
  					classnodes = null;
  				}
  				
  			}
  			clsSet = null;
  		}catch(Exception e){
  			logger.error("根据jar文件中所包含类、方法生成具体树异常!");
  		}
  	}
  	
  	
  	/**
  	 * 根据jar文件中所包含类、方法生成具体树
  	 * @param jarUrl jar路径{ex:e:\a.jar}
  	 * @param node node父节点
  	 * @param classLoader
  	 */
  	private static void loadClassTreeServiceBehavior(String jarUrl,CheckNode node,DynamicClassLoader classLoader){
  		try{
  			Set<Class<?>> clsSet = ClassHelper.getClassFromJar(jarUrl, classLoader);
  			for(Class<?> cls : clsSet) {
  				//如果存在ServiceContract的注解则添加
  				if(cls.getAnnotation(ServiceBehavior.class) != null){//定义接口实现类
  					CheckNode classnodes = new CheckNode(cls.getName());//类名
  					node.add(classnodes);
  					
  					Method [] methods = cls.getDeclaredMethods();/**当前类包含方法*/
  					if(methods != null){
  						for(Method m : methods){
  							if(Modifier.isPublic(m.getModifiers()) || Modifier.isProtected(m.getModifiers())){
  								//if(m.getAnnotation(OperationContract.class)!=null){
  									Class<?> methodParameter[] = m.getParameterTypes();/**该方法包含参数*/
  									String methodParameterStr = m.getName();
  									StringBuffer sbuffer = new StringBuffer();
  									if(methodParameter!=null){
  										for(int j=0,len=methodParameter.length;j<len;j++){
  											String nameStr = methodParameter[j].getName();
  											sbuffer.append(nameStr.substring(nameStr.lastIndexOf(".")+1));
  											if(j < len-1){
  												sbuffer.append(",");
  											}
  											nameStr = null;
  										}	
  									}
  									if(sbuffer!=null){
  										methodParameterStr = methodParameterStr+"("+sbuffer.toString()+")";
  									}
  									CheckNode methodnodes = new CheckNode(methodParameterStr);
  									classnodes.add(methodnodes);
  									methodnodes = null;
  									methodParameterStr = null;
  									sbuffer = null;
  								//}
  							}
  						}
  					}
  					classnodes = null;
  				}
  				
  			}
  			clsSet = null;
  		}catch(Exception e){
  			logger.error("根据jar文件中所包含类、方法生成具体树异常!");
  		}
  	}
  	
  	
  	/**
  	 * 鼠标点击监听
  	 */
  	class NodeSelectionListener extends MouseAdapter {
  		JTree tree;
  		NodeSelectionListener(JTree tree) {
  			this.tree = tree;
  		}
  		public void mouseClicked(MouseEvent e) {
  			int x = e.getX();
  			int y = e.getY();
  			int row = tree.getRowForLocation(x, y);
  			TreePath path = tree.getPathForRow(row);			
  			if (path != null) {
  				CheckNode node = (CheckNode) path.getLastPathComponent();				
  				if(node!=null){
  					boolean isSelected = !(node.isSelected());
  					node.setSelected(isSelected);
  					if (isSelected) {
  						tree.expandPath(path);
  						checkSubTree(path,tree);
  					} else {
  						tree.collapsePath(path);
  						uncheckSubTree(path,tree);
  					}
  					((DefaultTreeModel) tree.getModel()).nodeChanged(node);
  					if (row == 0) {
  						tree.revalidate();
  						tree.repaint();
  					}
  				}
  			}
  		}
  	}
  	
  	/**
  	 * 选中树中记录以及子记录
  	 * @param path 当前路径
  	 * @param tree
  	 */
  	private static void checkSubTree(final TreePath path,JTree tree) {
  		addToCheckedPathsSet(path);
  		for (int childIndex = 0; childIndex < getChildrenNumber(path,tree); childIndex++) {
  		    TreePath childPath = path.pathByAddingChild(tree.getModel().getChild(path.getLastPathComponent(), childIndex));
  		    checkSubTree(childPath,tree);
  		}
  	}
  	/**
  	 * 取消树中选中记录以及子记录
  	 * @param path 当前路径
  	 * @param tree
  	 */
  	private static void uncheckSubTree(final TreePath path,JTree tree) {
  		romeToCheckedPathsSet(path);
  		for (int childIndex = 0; childIndex < getChildrenNumber(path,tree); childIndex++) {
  		    TreePath childPath = path.pathByAddingChild(tree.getModel().getChild(path.getLastPathComponent(), childIndex));
  		    uncheckSubTree(childPath,tree);
  		}
  	}
  	/**
  	 * 获得子树数目
  	 * @param path
  	 * @param tree
  	 * @return
  	 */
  	private static int getChildrenNumber(final TreePath path,final JTree tree){
  		Object node = path.getLastPathComponent();
  		return tree.getModel().getChildCount(node);
  	}
  	
  	private static void romeToCheckedPathsSet(TreePath path) {
  		checkedPathsSet.remove(path);
  	}
  	private static void addToCheckedPathsSet(TreePath path) {
  		checkedPathsSet.add(path);
  	}
  	/**
  	 * 返回选中记录集合
  	 * @return
  	 */
  	public static Set<TreePath> getCheckingPaths(){
  		return checkedPathsSet;
  	}
  }
  