1 /*
2  * @(#)MergeHelpUtilities.java	1.9 06/10/30
3  *
4  * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6  *
7  * This code is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License version 2 only, as
9  * published by the Free Software Foundation.  Sun designates this
10  * particular file as subject to the "Classpath" exception as provided
11  * by Sun in the LICENSE file that accompanied this code.
12  *
13  * This code is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16  * version 2 for more details (a copy is included in the LICENSE file that
17  * accompanied this code).
18  *
19  * You should have received a copy of the GNU General Public License version
20  * 2 along with this work; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
24  * CA 95054 USA or visit www.sun.com if you need additional information or
25  * have any questions.
26  */
27 
28 package javax.help;
29 
30 import javax.swing.tree.*;
31 import java.util.*;
32 import java.text.*;
33 import java.lang.reflect.Method;
34 
35 /**
36  * Common utilities for merge types
37  *
38  * @author  Richard Gregor
39  * @version	1.9	10/30/06
40  */
41 
42 public class MergeHelpUtilities extends Object {
43 
44 
45     /**
46      * Merge the nodes according the merging rules of the masterNode's
47      * merge type
48      *
49      * @param masterMergeType The fallback mergeType if masterNode does not have a mergeType
50      * @param masterNode The master node to merge into
51      * @param slaveNode A secondary node that will merge into the master node
52      */
mergeNodes(String masterMergeType, DefaultMutableTreeNode masterNode, DefaultMutableTreeNode slaveNode)53     public static void mergeNodes(String masterMergeType,
54 				  DefaultMutableTreeNode masterNode,
55 				  DefaultMutableTreeNode slaveNode) {
56 	if (slaveNode.isLeaf()) {
57 	    return;
58 	}
59 	String mergeType = getMergeType(masterNode);
60 	if (mergeType == null) {
61 	    mergeType = masterMergeType;
62 	}
63 
64 	Class klass;
65 	Class types[] =  { TreeNode.class,
66 			   TreeNode.class };
67 	Method m;
68 	Object args[] = { masterNode, slaveNode };
69 	try {
70 	    klass = Class.forName(mergeType);
71 	    m = klass.getDeclaredMethod("mergeNodes", types);
72 	    m.invoke(null, args);
73 	} catch (Exception ex) {
74 	    ex.printStackTrace();
75 	    throw new RuntimeException
76 		("Could not find or execute mergeNodes for " +
77 		 mergeType);
78 	}
79     }
80 
81     /**
82      * Merge a nodes children according the merging rules of the node's
83      * merge type
84      *
85      * @param masterMergeType The fallback mergeType if masterNode does not have a mergeType
86      * @param node The node
87      */
mergeNodeChildren(String masterMergeType, DefaultMutableTreeNode node)88     public static void mergeNodeChildren(String masterMergeType, DefaultMutableTreeNode node) {
89 	if (node.isLeaf()) {
90 	    return;
91 	}
92 	String mergeType = getMergeType(node);
93 	if (mergeType == null) {
94 	    mergeType = masterMergeType;
95 	}
96 	Class klass;
97 	Class types[] =  { TreeNode.class };
98 	Method m;
99 	Object args[] = { node };
100 	try {
101 	    klass = Class.forName(mergeType);
102 	    m = klass.getDeclaredMethod("mergeNodeChildren", types);
103 	    m.invoke(null, args);
104 	} catch (Exception ex) {
105 	    ex.printStackTrace();
106 	    throw new RuntimeException
107 		("Could not find or execute mergeNodeChildren for " +
108 		 mergeType);
109 	}
110     }
111 
112     /**
113      * Returns node's merge type
114      *
115      * @param node The node
116      * @return The node's merge type
117      */
getMergeType(DefaultMutableTreeNode node)118     private static String getMergeType(DefaultMutableTreeNode node) {
119         TreeItem item = (TreeItem)node.getUserObject();
120         if (item == null) {
121             return null;
122         } else {
123             return item.getMergeType();
124 	}
125     }
126 
127     /**
128      * Returns name of node
129      *
130      * @param node The node
131      * @return The name of node
132      */
getNodeName(DefaultMutableTreeNode node)133     public static String getNodeName(DefaultMutableTreeNode node) {
134 	if (node == null) {
135 	    return null;
136 	}
137         TreeItem item = (TreeItem)node.getUserObject();
138 	if (item == null) {
139 	    return null;
140 	}
141         return item.getName();
142     }
143 
144     /**
145      * Returns node with given name
146      *
147      * @param parent The parent node
148      * @param name The name of child
149      * @return The child with given name
150      */
getChildWithName(DefaultMutableTreeNode parent,String name)151     public static DefaultMutableTreeNode getChildWithName(DefaultMutableTreeNode parent,String name) {
152         DefaultMutableTreeNode childAtI = null;
153         DefaultMutableTreeNode result = null;
154 
155         for (int i = 0; i < parent.getChildCount(); i++) {
156             childAtI = (DefaultMutableTreeNode)parent.getChildAt(i);
157             if (getNodeName(childAtI).equals(name)) {
158                 result = childAtI;
159                 break;
160             }
161         }
162         return result;
163 
164     }
165 
166     /**
167      * Returns locale of node
168      *
169      * @param node The node
170      * @return The locale object
171      */
getLocale(DefaultMutableTreeNode node)172     public static Locale getLocale(DefaultMutableTreeNode node) {
173 	Locale locale = null;
174         TreeItem item = (TreeItem)node.getUserObject();
175         if (item != null) {
176             locale = item.getLocale();
177 	}
178 	if (locale == null) {
179             locale = Locale.getDefault();
180 	}
181 	return locale;
182     }
183 
184     /**
185      * Compares name of nodes
186      *
187      * @param master The master node
188      * @param slave The slave node
189      * @return negative is master is lexically lower than slave;
190      * positive if master is lexically higher than slave and zero if lexically
191      * identical.
192      */
compareNames(DefaultMutableTreeNode master, DefaultMutableTreeNode slave)193     public static int compareNames(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) {
194 
195         TreeItem masterItem = (TreeItem)master.getUserObject();
196         debug("haveEqualName - master:"+masterItem);
197         TreeItem slaveItem = (TreeItem)slave.getUserObject();
198         debug("haveEqualName - slave:"+slaveItem);
199 
200 	String masterName = masterItem.getName();
201         if (masterName == null) {
202             masterName = " ";
203 	}
204 
205 	String slaveName = slaveItem.getName();
206         if (slaveName == null) {
207             slaveName = " ";
208 	}
209 
210 	Collator collator = Collator.getInstance(getLocale(master));
211         return collator.compare(masterName, slaveName);
212     }
213 
214     /**
215      * Method for comparing ID of nodes
216      *
217      * @param master The master node
218      * @param slave The slave node
219      * @return True if ID is the same
220      */
haveEqualID(DefaultMutableTreeNode master, DefaultMutableTreeNode slave)221     public static boolean haveEqualID(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) {
222         TreeItem masterItem = (TreeItem)master.getUserObject();
223         TreeItem slaveItem = (TreeItem)slave.getUserObject();
224 
225         if (masterItem.getID() == null) {
226             if (slaveItem.getID() == null) {
227                 return true;
228             } else {
229                 return false;
230 	    }
231         } else {
232             if (slaveItem.getID() == null) {
233                 return false;
234 	    }
235 	}
236 
237         //items are not null
238 
239         Map.ID masterMapID = masterItem.getID();
240         Map.ID slaveMapID = slaveItem.getID();
241 
242         if (masterMapID.id == null) {
243             if (slaveMapID.id == null) {
244                 return true;
245             } else {
246                 return false;
247 	    }
248         } else {
249             if (slaveMapID.id == null) {
250                 return false;
251 	    }
252 	}
253 
254         return masterMapID.id.equals(slaveMapID.id);
255     }
256 
257 
258     /**
259      * Marks nodes with the same name but diferent IDs with their HelpSet title
260      *
261      * @param master The master node to mark
262      * @param slave The slave node to mark
263      */
264 
markNodes(DefaultMutableTreeNode master, DefaultMutableTreeNode slave)265     public static void markNodes(DefaultMutableTreeNode master, DefaultMutableTreeNode slave) {
266         debug("MarkNodes");
267         TreeItem masterItem = (TreeItem)master.getUserObject();
268         TreeItem slaveItem = (TreeItem)slave.getUserObject();
269         HelpSet masterHS = masterItem.getHelpSet();
270         HelpSet slaveHS = slaveItem.getHelpSet();
271 
272 	if (masterItem.getName() != null) {
273 	    masterItem.setName(masterItem.getName()+"("+masterHS.getTitle()+")");
274 	} else {
275 	    masterItem.setName(masterItem.getName()+"("+masterHS.getTitle()+")");
276 	}
277 	if (slaveItem.getName() != null) {
278 	    slaveItem.setName(slaveItem.getName()+"("+slaveHS.getTitle()+")");
279 	} else {
280 	    slaveItem.setName(slaveItem.getName()+"("+slaveHS.getTitle()+")");
281 	}
282     }
283 
284     private static boolean debug = false;
debug(String msg)285     private static void debug(String msg) {
286         if (debug) {
287             System.out.println("MergeHelpUtilities :"+msg);
288 	}
289     }
290 }
291 
292