2
* @(#)FlatMap.java 1.36 06/10/30
4
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
31
import java.net.URLConnection;
32
import java.net.MalformedURLException;
36
import javax.help.event.*;
37
import javax.help.Map.ID;
38
import com.sun.java.help.impl.*;
41
* A FlatMap is a simple implementation of a Map. It is used to represent a
42
* Map for a single file.
44
* @author Eduardo Pelegri-Llopart
45
* @version 1.18 01/22/99
47
public class FlatMap implements Map, Serializable {
48
private URL base; // URL to this map
49
private ResourceBundle resource; // the resource
50
private HelpSet helpset; // the top HelpSet
53
* PublicID (known to this XML processor) to the DTD for version 1.0 of the Map
55
public static final String publicIDString =
56
"-//Sun Microsystems Inc.//DTD JavaHelp Map Version 1.0//EN";
59
* PublicID (known to this XML processor) to the DTD for version 1.0 of the Map
61
public static final String publicIDString_V2 =
62
"-//Sun Microsystems Inc.//DTD JavaHelp Map Version 2.0//EN";
65
* Create a FlatMap from a given URL.
67
* @param source The URL that is the source for all references in this Map.
68
* @param hs The HelpSet providing "context" for this Map.
69
* @throws IllegalArgumentException if hs doesn't have nested HelpSets.
71
public FlatMap(URL base, HelpSet hs) throws IOException {
72
debug("Creating FlatMap for: "+base);
74
// Verify that this helpset indeed does not have nested HelpSets.
75
for (Enumeration e = hs.getHelpSets();
76
e.hasMoreElements(); ) {
77
throw new IllegalArgumentException
78
("Cannot create - HelpSet is not flat");
81
// InputStream is = base.openStream();
82
// resource = new MapResourceBundle(is);
83
resource = new FlatMapResourceBundle(base);
89
* The HelpSet for this Map.
91
public HelpSet getHelpSet() {
96
* Determines whether the given ID is valid. If hs is null
99
* @param id The String ID.
100
* @param hs The HelpSet against which to resolve the string.
101
* @return True if id is valid, false if not valid.
104
public boolean isValidID(String id, HelpSet hs) {
105
debug("isValidID "+id);
108
String tmp = resource.getString(id);
109
} catch (MissingResourceException e) {
116
* Gets an enumeration of all the IDs in a Map.
118
* @return An enumeration of all the IDs in a Map.
120
public Enumeration getAllIDs() {
121
return new FlatEnumeration(resource.getKeys(), helpset);
125
* Gets the URL that corresponds to a given ID in the map.
127
* @param iden The iden to get the URL for. If iden is null it is
128
* treated as an unresolved ID and will return null.
129
* @return URL The matching URL. Null if this map cannot solve the ID
130
* @exception MalformedURLException if the URLspecification found is malformed
132
public URL getURLFromID(ID iden) throws MalformedURLException {
133
debug("getURLFromID("+iden+")");
136
HelpSet hs = iden.hs;
142
tmp = resource.getString(id);
143
URL back = new URL(base, tmp);
145
} catch (MissingResourceException e) {
151
* Determines if the URL corresponds to an ID in the Map.
153
* @param url The URL to check on.
154
* @return true If this is an ID, otherwise false.
156
public boolean isID(URL url) {
158
for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) {
160
String key = (String) e.nextElement();
161
tmp = new URL(base, (String) resource.getObject(key));
162
// sameFile() ignores the anchor! - epll
163
if (url.sameFile(tmp) == true) {
166
} catch (Exception ex) {
174
* Gets the ID for this URL.
176
* @param url The URL to get the ID for.
177
* @return The id (Map.ID) or null if URL is not an ID.
179
public ID getIDFromURL(URL url) {
182
if (url == null) return null;
183
String urlString = url.toExternalForm();
184
for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) {
185
String key = (String) e.nextElement();
187
tmp = resource.getString(key);
188
tmpURL = new URL(base, tmp);
190
// Sometimes tmp will be null because not all keys are ids
191
if (tmpURL == null) continue;
192
String tmpString = tmpURL.toExternalForm();
193
if (urlString.compareTo(tmpString) == 0) {
194
return ID.create(key, helpset);
196
} catch (Exception ex) {
203
* Determines the ID that is "closest" to this URL (with a given anchor).
205
* The definition of this is up to the implementation of Map. In particular,
206
* it may be the same as getIDFromURL().
209
* @return The closest ID in this map to the given URL
211
public ID getClosestID(URL url) {
212
return getIDFromURL(url);
217
* Determines the IDs related to this URL.
219
* @param URL The URL to compare the Map IDs to.
220
* @return Enumeration of Map.IDs
222
public Enumeration getIDs(URL url) {
225
Vector ids = new Vector();
226
for (Enumeration e = resource.getKeys() ; e.hasMoreElements() ;) {
227
String key = (String) e.nextElement();
229
tmp = resource.getString(key);
230
tmpURL = new URL(base, tmp);
231
if (url.sameFile(tmpURL) == true) {
234
} catch (Exception ex) {
237
return new FlatEnumeration(ids.elements(), helpset);
240
private static class FlatEnumeration implements Enumeration {
241
private Enumeration e;
244
public FlatEnumeration(Enumeration e, HelpSet hs) {
249
public boolean hasMoreElements() {
250
return e.hasMoreElements();
253
public Object nextElement() {
256
back = ID.create((String) e.nextElement(), hs);
257
} catch (Exception ex) {
265
* FlatMapResourceBundle is a ResourceBundle but unlike most
266
* ResourceBundles it is not locale-based and is loaded via the
267
* constructor, not getBundle.
269
protected class FlatMapResourceBundle extends ResourceBundle
270
implements ParserListener, Serializable
273
private Hashtable lookup = null;
274
private boolean startedmap;
278
* Creates the FlatMap from the data.
280
public FlatMapResourceBundle(URL url) {
284
URLConnection uc = url.openConnection();
285
src = XmlReader.createReader(uc);
288
} catch (Exception e) {
289
reportMessage("Exception caught while parsing "+url+" "+
290
e.toString(), false);
293
for (Enumeration e = lookup.keys() ; e.hasMoreElements() ;) {
294
String key1 = (String) e.nextElement();
295
String url1 = (String) lookup.get(key1);
300
* Overrides ResourceBundle, same semantics.
302
public final Object handleGetObject(String key) {
303
return lookup.get(key); // this class ignores locales
307
* Implements ResourceBundle.getKeys.
309
public Enumeration getKeys() {
310
return lookup.keys();
314
* Parses a reader into a MutableTreeNode
315
* Only one of these at a time.
317
synchronized void parse(Reader src)
320
lookup = new Hashtable(10);
322
Parser parser = new Parser(src); // the XML parser instance
323
parser.addParserListener(this);
330
public void tagFound(ParserEvent e) {
331
Locale locale = null;
332
Tag tag = e.getTag();
333
FlatMap.debug("TagFound: "+tag.name);
334
TagProperties attr = tag.atts;
336
// Nothing tricky about mapID it doesn't have any hierarchy to it.
337
if (tag.name.equals("mapID")) {
339
parsingError("map.invalidMapFormat");
342
String target = null;
345
target = attr.getProperty("target");
346
url = attr.getProperty("url");
348
if (target == null || url == null) {
349
reportMessage("Failure in mapID Creation;", true);
350
reportMessage(" target: "+ target, true);
351
reportMessage(" url: "+ url, true);
354
lookup.put(target, url);
356
} else if (tag.name.equals("map")) {
359
String version = attr.getProperty("version");
360
if (version != null &&
361
(version.compareTo("1.0") != 0 &&
362
version.compareTo("2.0") != 0)) {
363
parsingError("map.unknownVersion", version);
367
parsingError("map.invalidMapFormat");
380
* A PI was parsed. This method is not intended to be of general use.
382
public void piFound(ParserEvent e) {
387
* A DOCTYPE was parsed. This method is not intended to be of general use.
389
public void doctypeFound(ParserEvent e) {
390
String publicID = e.getPublicId();
391
if (publicID == null ||
392
(publicID.compareTo(publicIDString) != 0 &&
393
publicID.compareTo(publicIDString_V2) != 0)) {
394
parsingError("map.wrongPublicID", publicID);
399
* A continous block of text was parsed.
401
public void textFound(ParserEvent e) {
402
// At the current time I don't care about text. All the text is
403
// within the attributes in the tag
406
// The remaing events from Parser are ignored
407
public void commentFound(ParserEvent e) {}
409
public void errorFound(ParserEvent e){
410
reportMessage(e.getText(), false);
414
private Vector messages = new Vector();
415
private boolean validParse = true;
418
* Reports an error message.
420
public void reportMessage(String msg, boolean validParse) {
421
messages.addElement(msg);
422
this.validParse = this.validParse && validParse;
426
* Enumerates all the error messages.
428
public Enumeration listMessages() {
429
return messages.elements();
433
* Parsing has ended. We are given a last chance to do something
436
private void parsingEnded() {
438
if (lookup != null) {
442
// A parse with problems...
443
FlatMap.debug("Parsing failed for "+source);
445
for (Enumeration e = messages.elements();
446
e.hasMoreElements();) {
447
String msg = (String) e.nextElement();
452
// little memory clean up
457
// Convenience methods
458
private void parsingError(String key) {
459
String s = HelpUtilities.getText(key);
460
reportMessage(s, false); // tree will be wrong
463
private void parsingError(String key, String s) {
464
String msg = HelpUtilities.getText(key, s);
465
reportMessage(msg, false); // tree will be wrong
471
* For printf debugging...
473
private static final boolean debug = false;
474
private static void debug(String str) {
476
System.out.println("FlatMap: " + str);