Thu, 02 Oct 2008 19:58:40 -0700
6754988: Update copyright year
Summary: Update for files that have been modified starting July 2008
Reviewed-by: ohair, tbell
1 /*
2 * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.doclets.internal.toolkit.util;
28 import com.sun.tools.doclets.internal.toolkit.*;
29 import com.sun.javadoc.*;
30 import java.util.*;
32 /**
33 * Process and manage grouping of packages, as specified by "-group" option on
34 * the command line.
35 * <p>
36 * For example, if user has used -group option as
37 * -group "Core Packages" "java.*" -group "CORBA Packages" "org.omg.*", then
38 * the packages specified on the command line will be grouped according to their
39 * names starting with either "java." or "org.omg.". All the other packages
40 * which do not fall in the user given groups, are grouped in default group,
41 * named as either "Other Packages" or "Packages" depending upon if "-group"
42 * option used or not at all used respectively.
43 * </p>
44 * <p>
45 * Also the packages are grouped according to the longest possible match of
46 * their names with the grouping information provided. For example, if there
47 * are two groups, like -group "Lang" "java.lang" and -group "Core" "java.*",
48 * will put the package java.lang in the group "Lang" and not in group "Core".
49 * </p>
50 *
51 * This code is not part of an API.
52 * It is implementation that is subject to change.
53 * Do not use it as an API
54 *
55 * @author Atul M Dambalkar
56 */
57 public class Group {
59 private static Group instance;
61 /**
62 * Map of regular expressions with the corresponding group name.
63 */
64 private Map<String,String> regExpGroupMap = new HashMap<String,String>();
66 /**
67 * List of regular expressions sorted according to the length. Regular
68 * expression with longest length will be first in the sorted order.
69 */
70 private List<String> sortedRegExpList = new ArrayList<String>();
72 /**
73 * List of group names in the same order as given on the command line.
74 */
75 private List<String> groupList = new ArrayList<String>();
77 /**
78 * Map of non-regular expressions(possible package names) with the
79 * corresponding group name.
80 */
81 private Map<String,String> pkgNameGroupMap = new HashMap<String,String>();
83 /**
84 * The global configuration information for this run.
85 */
86 private final Configuration configuration;
88 /**
89 * Since we need to sort the keys in the reverse order(longest key first),
90 * the compare method in the implementing class is doing the reverse
91 * comparison.
92 */
93 private static class MapKeyComparator implements Comparator<String> {
94 public int compare(String key1, String key2) {
95 return key2.length() - key1.length();
96 }
97 }
99 private Group(Configuration configuration) {
100 this.configuration = configuration;
101 }
103 public static Group getInstance(Configuration configuration) {
104 if (instance == null) {
105 instance = new Group(configuration);
106 }
107 return instance;
108 }
110 /**
111 * Depending upon the format of the package name provided in the "-group"
112 * option, generate two separate maps. There will be a map for mapping
113 * regular expression(only meta character allowed is '*' and that is at the
114 * end of the regular expression) on to the group name. And another map
115 * for mapping (possible) package names(if the name format doesen't contain
116 * meta character '*', then it is assumed to be a package name) on to the
117 * group name. This will also sort all the regular expressions found in the
118 * reverse order of their lengths, i.e. longest regular expression will be
119 * first in the sorted list.
120 *
121 * @param groupname The name of the group from -group option.
122 * @param pkgNameFormList List of the package name formats.
123 */
124 public boolean checkPackageGroups(String groupname,
125 String pkgNameFormList) {
126 StringTokenizer strtok = new StringTokenizer(pkgNameFormList, ":");
127 if (groupList.contains(groupname)) {
128 configuration.message.warning("doclet.Groupname_already_used", groupname);
129 return false;
130 }
131 groupList.add(groupname);
132 while (strtok.hasMoreTokens()) {
133 String id = strtok.nextToken();
134 if (id.length() == 0) {
135 configuration.message.warning("doclet.Error_in_packagelist", groupname, pkgNameFormList);
136 return false;
137 }
138 if (id.endsWith("*")) {
139 id = id.substring(0, id.length() - 1);
140 if (foundGroupFormat(regExpGroupMap, id)) {
141 return false;
142 }
143 regExpGroupMap.put(id, groupname);
144 sortedRegExpList.add(id);
145 } else {
146 if (foundGroupFormat(pkgNameGroupMap, id)) {
147 return false;
148 }
149 pkgNameGroupMap.put(id, groupname);
150 }
151 }
152 Collections.sort(sortedRegExpList, new MapKeyComparator());
153 return true;
154 }
156 /**
157 * Search if the given map has given the package format.
158 *
159 * @param map Map to be searched.
160 * @param pkgFormat The pacakge format to search.
161 *
162 * @return true if package name format found in the map, else false.
163 */
164 boolean foundGroupFormat(Map map, String pkgFormat) {
165 if (map.containsKey(pkgFormat)) {
166 configuration.message.error("doclet.Same_package_name_used", pkgFormat);
167 return true;
168 }
169 return false;
170 }
172 /**
173 * Group the packages according the grouping information provided on the
174 * command line. Given a list of packages, search each package name in
175 * regular expression map as well as package name map to get the
176 * corresponding group name. Create another map with mapping of group name
177 * to the package list, which will fall under the specified group. If any
178 * package doesen't belong to any specified group on the comamnd line, then
179 * a new group named "Other Packages" will be created for it. If there are
180 * no groups found, in other words if "-group" option is not at all used,
181 * then all the packages will be grouped under group "Packages".
182 *
183 * @param packages Packages specified on the command line.
184 */
185 public Map<String,List<PackageDoc>> groupPackages(PackageDoc[] packages) {
186 Map<String,List<PackageDoc>> groupPackageMap = new HashMap<String,List<PackageDoc>>();
187 String defaultGroupName =
188 (pkgNameGroupMap.isEmpty() && regExpGroupMap.isEmpty())?
189 configuration.message.getText("doclet.Packages") :
190 configuration.message.getText("doclet.Other_Packages");
191 // if the user has not used the default group name, add it
192 if (!groupList.contains(defaultGroupName)) {
193 groupList.add(defaultGroupName);
194 }
195 for (int i = 0; i < packages.length; i++) {
196 PackageDoc pkg = packages[i];
197 String pkgName = pkg.name();
198 String groupName = pkgNameGroupMap.get(pkgName);
199 // if this package is not explicitly assigned to a group,
200 // try matching it to group specified by regular expression
201 if (groupName == null) {
202 groupName = regExpGroupName(pkgName);
203 }
204 // if it is in neither group map, put it in the default
205 // group
206 if (groupName == null) {
207 groupName = defaultGroupName;
208 }
209 getPkgList(groupPackageMap, groupName).add(pkg);
210 }
211 return groupPackageMap;
212 }
214 /**
215 * Search for package name in the sorted regular expression
216 * list, if found return the group name. If not, return null.
217 *
218 * @param pkgName Name of package to be found in the regular
219 * expression list.
220 */
221 String regExpGroupName(String pkgName) {
222 for (int j = 0; j < sortedRegExpList.size(); j++) {
223 String regexp = sortedRegExpList.get(j);
224 if (pkgName.startsWith(regexp)) {
225 return regExpGroupMap.get(regexp);
226 }
227 }
228 return null;
229 }
231 /**
232 * For the given group name, return the package list, on which it is mapped.
233 * Create a new list, if not found.
234 *
235 * @param map Map to be searched for gorup name.
236 * @param groupname Group name to search.
237 */
238 List<PackageDoc> getPkgList(Map<String,List<PackageDoc>> map, String groupname) {
239 List<PackageDoc> list = map.get(groupname);
240 if (list == null) {
241 list = new ArrayList<PackageDoc>();
242 map.put(groupname, list);
243 }
244 return list;
245 }
247 /**
248 * Return the list of groups, in the same order as specified
249 * on the command line.
250 */
251 public List getGroupList() {
252 return groupList;
253 }
254 }