001: package prefuse.util.io;
002:
003: import java.awt.Component;
004: import java.io.File;
005: import java.io.FileInputStream;
006: import java.io.IOException;
007: import java.io.InputStream;
008: import java.net.URL;
009: import java.util.logging.Logger;
010: import java.util.zip.GZIPInputStream;
011:
012: import javax.swing.JFileChooser;
013:
014: import prefuse.data.Graph;
015: import prefuse.data.Table;
016: import prefuse.data.io.CSVTableReader;
017: import prefuse.data.io.DelimitedTextTableReader;
018: import prefuse.data.io.GraphMLReader;
019: import prefuse.data.io.GraphReader;
020: import prefuse.data.io.TableReader;
021: import prefuse.data.io.TreeMLReader;
022: import prefuse.util.StringLib;
023: import prefuse.util.collections.ByteArrayList;
024:
025: /**
026: * Library routines for input/output tasks.
027: *
028: * @author <a href="http://jheer.org">jeffrey heer</a>
029: */
030: public class IOLib {
031:
032: private IOLib() {
033: // disallow instantiation
034: }
035:
036: /**
037: * Indicates if a given String is a URL string. Checks to see if the string
038: * begins with the "http:/", "ftp:/", or "file:/" protocol strings.
039: * @param s the string to check
040: * @return true if a url string matching the listed protocols,
041: * false otherwise
042: */
043: public static boolean isUrlString(String s) {
044: return s.startsWith("http:/") || s.startsWith("ftp:/")
045: || s.startsWith("file:/");
046: }
047:
048: /**
049: * From a string description, attempt to generate a URL object. The string
050: * may point to an Internet location (e.g., http:// or ftp:// URL),
051: * a resource on the class path (resulting in a resource URL that points
052: * into the current classpath), or a file on the local filesystem
053: * (resulting in a file:// URL). The String will be checked in that order
054: * in an attempt to resolve it to a valid URL.
055: * @param location the location string for which to get a URL object
056: * @return a URL object, or null if the location string could not be
057: * resolved
058: */
059: public static URL urlFromString(String location) {
060: return urlFromString(location, null, true);
061: }
062:
063: /**
064: * From a string description, attempt to generate a URL object. The string
065: * may point to an Internet location (e.g., http:// or ftp:// URL),
066: * a resource on the class path (resulting in a resource URL that points
067: * into the current classpath), or, if the <code>includeFileSystem</code>
068: * flag is true, a file on the local filesystem
069: * (resulting in a file:// URL). The String will be checked in that order
070: * in an attempt to resolve it to a valid URL.
071: * @param location the location string for which to get a URL object
072: * @param referrer the class to check for classpath resource items, the
073: * location string will be resolved against the package/folder containing
074: * this class
075: * @param includeFileSystem indicates if the file system should be
076: * included in the search to resolve the location String
077: * @return a URL object, or null if the location string could not be
078: * resolved
079: */
080: public static URL urlFromString(String location, Class referrer,
081: boolean includeFileSystem) {
082: URL url = null;
083: if (isUrlString(location)) {
084: // explicit URL string
085: try {
086: url = new URL(location);
087: } catch (Exception e) {
088: e.printStackTrace();
089: }
090: } else {
091: // attempt to get a URL pointing into the classpath
092: if (referrer != null)
093: url = referrer.getResource(location);
094: else
095: url = IOLib.class.getResource(location);
096:
097: if (url == null && !location.startsWith("/"))
098: url = IOLib.class.getResource("/" + location);
099:
100: if (includeFileSystem && url == null) {
101: // if still not found, check the file system
102: File f = new File(location);
103: if (f.exists()) {
104: try {
105: url = f.toURI().toURL();
106: } catch (Exception e) {
107: }
108: }
109: }
110: }
111: return url;
112: }
113:
114: /**
115: * Get an input string corresponding to the given location string. The
116: * string will first be resolved to a URL and an input stream will be
117: * requested from the URL connection. If this fails, the location will
118: * be resolved against the file system. Also, if a gzip file is found,
119: * the input stream will also be wrapped by a GZipInputStream. If the
120: * location string can not be resolved, a null value is returned
121: * @param location the location string
122: * @return an InputStream for the resolved location string
123: * @throws IOException if an input/ouput error occurs
124: */
125: public static InputStream streamFromString(String location)
126: throws IOException {
127: InputStream is = null;
128:
129: // try to get a working url from the string
130: URL url = urlFromString(location, null, false);
131: if (url != null) {
132: is = url.openStream();
133: } else {
134: // if that failed, try the file system
135: File f = new File(location);
136: if (f.exists())
137: is = new FileInputStream(f);
138: }
139:
140: if (is == null) {
141: return null; // couldn't find it
142: } else if (isGZipFile(location)) {
143: return new GZIPInputStream(is);
144: } else {
145: return is;
146: }
147: }
148:
149: /**
150: * Returns the extension for a file or null if there is none
151: * @param f the input file
152: * @return the file extension, or null if none
153: */
154: public static String getExtension(File f) {
155: return (f != null ? getExtension(f.getName()) : null);
156: }
157:
158: /**
159: * Indicates if the given file ends with a file extension of
160: * ".gz" or ".Z", indicating a GZip file.
161: * @param file a String of the filename or URL of the file
162: * @return true if the extension is ".gz" or ".Z", false otherwise
163: */
164: public static boolean isGZipFile(String file) {
165: String ext = getExtension(file);
166: return "gz".equals(ext) || "z".equals(ext);
167: }
168:
169: /**
170: * Indicates if the given file ends with a file extension of
171: * ".zip", indicating a Zip file.
172: * @param file a String of the filename or URL of the file
173: * @return true if the extension is ".zip", false otherwise
174: */
175: public static boolean isZipFile(String file) {
176: return "zip".equals(getExtension(file));
177: }
178:
179: /**
180: * Returns the extension for a file or null if there is none
181: * @param filename the input filename
182: * @return the file extension, or null if none
183: */
184: public static String getExtension(String filename) {
185: int i = filename.lastIndexOf('.');
186: if (i > 0 && i < filename.length() - 1) {
187: return filename.substring(i + 1).toLowerCase();
188: } else {
189: return null;
190: }
191: }
192:
193: /**
194: * Reads an input stream into a list of byte values.
195: * @param is the input stream to read
196: * @return a ByteArrayList containing the contents of the input stream
197: * @throws IOException if an input/ouput error occurs
198: */
199: public static ByteArrayList readAsBytes(InputStream is)
200: throws IOException {
201: ByteArrayList buf = new ByteArrayList();
202: byte[] b = new byte[8192];
203: int nread = -1;
204: while ((nread = is.read(b)) >= 0) {
205: buf.add(b, 0, nread);
206: }
207: return buf;
208: }
209:
210: /**
211: * Reads an input stream into a single String result.
212: * @param is the input stream to read
213: * @return a String containing the contents of the input stream
214: * @throws IOException if an input/ouput error occurs
215: */
216: public static String readAsString(InputStream is)
217: throws IOException {
218: StringBuffer buf = new StringBuffer();
219: byte[] b = new byte[8192];
220: int nread = -1;
221: while ((nread = is.read(b)) >= 0) {
222: String s = new String(b, 0, nread);
223: buf.append(s);
224: }
225: return buf.toString();
226: }
227:
228: /**
229: * Reads data pulled from the given location string into a single String
230: * result. The method attempts to retrieve an InputStream using the
231: * {@link #streamFromString(String)} method, then read the input stream
232: * into a String result.
233: * @param location the location String
234: * @return a String with the requested data
235: * @throws IOException if an input/ouput error occurs
236: * @see #streamFromString(String)
237: */
238: public static String readAsString(String location)
239: throws IOException {
240: return readAsString(streamFromString(location));
241: }
242:
243: // ------------------------------------------------------------------------
244:
245: /**
246: * Present a file chooser dialog for loading a Table data set.
247: * @param c user interface component from which the request is being made
248: * @return a newly loaded Table, or null if not found or action canceled
249: */
250: public static Table getTableFile(Component c) {
251: JFileChooser jfc = new JFileChooser();
252: jfc.setDialogType(JFileChooser.OPEN_DIALOG);
253: jfc.setDialogTitle("Open Table File");
254: jfc.setAcceptAllFileFilterUsed(false);
255:
256: SimpleFileFilter ff;
257:
258: // TODO: have this generate automatically
259: // tie into PrefuseConfig??
260:
261: // CSV
262: ff = new SimpleFileFilter("csv",
263: "Comma Separated Values (CSV) File (*.csv)",
264: new CSVTableReader());
265: ff.addExtension("gz");
266: jfc.setFileFilter(ff);
267:
268: // Pipe-Delimited
269: ff = new SimpleFileFilter("txt",
270: "Pipe-Delimited Text File (*.txt)",
271: new DelimitedTextTableReader("|"));
272: ff.addExtension("gz");
273: jfc.setFileFilter(ff);
274:
275: // Tab-Delimited
276: ff = new SimpleFileFilter("txt",
277: "Tab-Delimited Text File (*.txt)",
278: new DelimitedTextTableReader());
279: ff.addExtension("gz");
280: jfc.setFileFilter(ff);
281:
282: int retval = jfc.showOpenDialog(c);
283: if (retval != JFileChooser.APPROVE_OPTION)
284: return null;
285:
286: File f = jfc.getSelectedFile();
287: ff = (SimpleFileFilter) jfc.getFileFilter();
288: TableReader tr = (TableReader) ff.getUserData();
289:
290: try {
291: return tr.readTable(streamFromString(f.getAbsolutePath()));
292: } catch (Exception e) {
293: Logger.getLogger(IOLib.class.getName()).warning(
294: e.getMessage() + "\n" + StringLib.getStackTrace(e));
295: return null;
296: }
297: }
298:
299: /**
300: * Present a file chooser dialog for loading a Graph or Tree data set.
301: * @param c user interface component from which the request is being made
302: * @return a newly loaded Graph, or null if not found or action canceled
303: */
304: public static Graph getGraphFile(Component c) {
305: JFileChooser jfc = new JFileChooser();
306: jfc.setDialogType(JFileChooser.OPEN_DIALOG);
307: jfc.setDialogTitle("Open Graph or Tree File");
308: jfc.setAcceptAllFileFilterUsed(false);
309:
310: SimpleFileFilter ff;
311:
312: // TODO: have this generate automatically
313: // tie into PrefuseConfig??
314:
315: // TreeML
316: ff = new SimpleFileFilter("xml",
317: "TreeML File (*.xml, *.treeml)", new TreeMLReader());
318: ff.addExtension("treeml");
319: ff.addExtension("gz");
320: jfc.setFileFilter(ff);
321:
322: // GraphML
323: ff = new SimpleFileFilter("xml",
324: "GraphML File (*.xml, *.graphml)", new GraphMLReader());
325: ff.addExtension("graphml");
326: ff.addExtension("gz");
327: jfc.setFileFilter(ff);
328:
329: int retval = jfc.showOpenDialog(c);
330: if (retval != JFileChooser.APPROVE_OPTION)
331: return null;
332:
333: File f = jfc.getSelectedFile();
334: ff = (SimpleFileFilter) jfc.getFileFilter();
335: GraphReader gr = (GraphReader) ff.getUserData();
336:
337: try {
338: return gr.readGraph(streamFromString(f.getAbsolutePath()));
339: } catch (Exception e) {
340: Logger.getLogger(IOLib.class.getName()).warning(
341: e.getMessage() + "\n" + StringLib.getStackTrace(e));
342: return null;
343: }
344: }
345:
346: } // end of class IOLib
|