View Javadoc

1   package net.sf.jpkgmk;
2   
3   import java.io.File;
4   import java.io.FileInputStream;
5   import java.io.IOException;
6   import java.io.InputStream;
7   import java.io.InputStreamReader;
8   import java.io.Reader;
9   import java.io.StringReader;
10  import java.nio.charset.Charset;
11  
12  import net.sf.jpkgmk.util.LineCountingReader;
13  import net.sf.jpkgmk.util.StreamUtil;
14  import net.sf.jpkgmk.util.StringUtil;
15  
16  import org.apache.commons.logging.Log;
17  import org.apache.commons.logging.LogFactory;
18  
19  /**
20   * Abstract class that provides some convenience methods for parsing files, strings etc. line by line.
21   * @author gommma (gommma AT users.sourceforge.net)
22   * @author Last changed by: $Author: gommma $
23   * @version $Revision: 2 $ $Date: 2008-08-20 21:14:19 +0200 (Mi, 20 Aug 2008) $
24   * @since 1.0
25   * 
26   * @param <T>
27   */
28  public abstract class AbstractParser<T> 
29  {
30  	public static final char DEFAULT_LINE_DELIMITER = ' ';
31  
32  	private Log log = LogFactory.getLog(AbstractParser.class);
33  
34  	
35  	public AbstractParser()
36  	{
37  	}
38  	
39  	
40  	/**
41  	 * Parses the data from the given reader and returns the parsed object representing all these data.
42  	 * @param data The input to be parsed
43  	 * @return The created object read from the given input data
44  	 * @throws IOException When something goes wrong during the {@link LineCountingReader#readLine()} invocation
45  	 * @see AbstractParser#parse(Reader)
46  	 */
47  	public T parse(String data) throws IOException
48  	{
49  		return parse(new StringReader(data));
50  	}
51  	
52  	/**
53  	 * Parses the data from the given reader and returns the parsed object representing all these data.
54  	 * @param file The input to be parsed
55  	 * @return The created object read from the given input data
56  	 * @throws IOException When something goes wrong during the {@link LineCountingReader#readLine()} invocation
57  	 * @see AbstractParser#parse(Reader)
58  	 */
59  	public T parse(File file) throws IOException
60  	{
61  		if (file == null) {
62  			throw new NullPointerException(
63  					"The parameter 'file' must not be null");
64  		}
65  		
66  		InputStream inputStream = new FileInputStream(file);
67  		try {
68  			Charset charset = Charset.forName("US-ASCII");
69  			log.info("Using default character set " + charset + " for reading file " + file);
70  			Reader reader = new InputStreamReader(inputStream, charset);
71  			return this.parse(reader);
72  		}
73  		finally {
74  			StreamUtil.tryCloseStream(inputStream);
75  		}
76  	}
77  
78  	/**
79  	 * Parses the data from the given reader and returns the parsed object representing all these data.
80  	 * @param data The input to be parsed
81  	 * @return The created object read from the given input data
82  	 * @throws IOException When something goes wrong during the {@link LineCountingReader#readLine()} invocation
83  	 */
84  	public T parse(Reader data) throws IOException
85  	{
86  		if (data == null) {
87  			throw new NullPointerException(
88  					"The parameter 'data' must not be null");
89  		}
90  
91  		T result = createResult();
92  		// Read the lines
93  		LineCountingReader reader = new LineCountingReader(data);
94  		try {
95  			String line = null;
96  			while((line=reader.readLine()) != null) {
97  				if(StringUtil.isNullOrEmpty(line)) {
98  					log.debug("Ignoring empty line " + reader.currentLineNumber());
99  					continue;
100 				}
101 				
102 				try {
103 					this.parseAndAddLine(line, result);
104 				}
105 				catch(Exception e) {
106 					throw new PackageException("Exception while parsing line " + reader.currentLineNumber() + ": " + e, e);
107 				}
108 			}
109 		}
110 		finally {
111 			StreamUtil.tryCloseStream(reader);
112 		}
113 		return result;
114 	}
115 	
116 	
117 	protected abstract T createResult();
118 
119 
120 	protected abstract void parseAndAddLine(String line, T resultObject);
121 	
122 
123 	/**
124 	 * Returns the items of the given line
125 	 * @param line
126 	 * @return
127 	 */
128 	public static final String[] getLineItems(String line)
129 	{
130 		String[] items = line.split(String.valueOf(DEFAULT_LINE_DELIMITER));
131 		return items;
132 	}
133 
134 }