Skip to content

Commit 50fad4d

Browse files
committed
Add flat file serializers and stub out XML serializers.
1 parent 17eea81 commit 50fad4d

File tree

9 files changed

+732
-1
lines changed

9 files changed

+732
-1
lines changed

httprpc/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ plugins {
2020
}
2121

2222
group = 'org.httprpc'
23-
version = '6.1.1'
23+
version = '6.2'
2424

2525
repositories {
2626
mavenCentral()
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package org.httprpc.io;
16+
17+
import java.io.IOException;
18+
import java.io.InputStream;
19+
import java.io.InputStreamReader;
20+
import java.io.Reader;
21+
import java.nio.charset.Charset;
22+
import java.util.ArrayList;
23+
import java.util.Iterator;
24+
import java.util.LinkedHashMap;
25+
import java.util.List;
26+
import java.util.Map;
27+
import java.util.NoSuchElementException;
28+
29+
/**
30+
* Flat file decoder.
31+
*/
32+
public class FlatFileDecoder {
33+
/**
34+
* Class representing a field.
35+
*/
36+
public static class Field {
37+
private String key;
38+
private int length;
39+
40+
/**
41+
* Constructs a new field.
42+
*
43+
* @param key
44+
* The field key.
45+
*
46+
* @param length
47+
* The field length.
48+
*/
49+
public Field(String key, int length) {
50+
if (key == null) {
51+
throw new IllegalArgumentException();
52+
}
53+
54+
if (length < 0) {
55+
throw new IllegalArgumentException();
56+
}
57+
58+
this.key = key;
59+
this.length = length;
60+
}
61+
62+
/**
63+
* Returns the field key.
64+
*
65+
* @return
66+
* The field key.
67+
*/
68+
public String getKey() {
69+
return key;
70+
}
71+
72+
/**
73+
* Returns the field length.
74+
*
75+
* @return
76+
* The field length.
77+
*/
78+
public int getLength() {
79+
return length;
80+
}
81+
}
82+
83+
// Cursor
84+
private static class Cursor implements Iterable<Map<String, String>> {
85+
private Reader reader;
86+
private List<Field> fields;
87+
88+
private ArrayList<String> values;
89+
90+
private StringBuilder valueBuilder = new StringBuilder();
91+
92+
private Iterator<Map<String, String>> iterator = new Iterator<Map<String, String>>() {
93+
private Boolean hasNext = null;
94+
95+
@Override
96+
public boolean hasNext() {
97+
if (hasNext == null) {
98+
try {
99+
values.clear();
100+
101+
readValues(reader, values);
102+
} catch (IOException exception) {
103+
throw new RuntimeException(exception);
104+
}
105+
106+
hasNext = !values.isEmpty();
107+
}
108+
109+
return hasNext.booleanValue();
110+
}
111+
112+
@Override
113+
public Map<String, String> next() {
114+
if (!hasNext()) {
115+
throw new NoSuchElementException();
116+
}
117+
118+
LinkedHashMap<String, String> row = new LinkedHashMap<>();
119+
120+
for (int i = 0, n = Math.min(fields.size(), values.size()); i < n; i++) {
121+
row.put(fields.get(i).getKey(), values.get(i));
122+
}
123+
124+
hasNext = null;
125+
126+
return row;
127+
}
128+
};
129+
130+
private static final int EOF = -1;
131+
132+
public Cursor(Reader reader, List<Field> fields) throws IOException {
133+
this.reader = reader;
134+
this.fields = fields;
135+
136+
values = new ArrayList<>(fields.size());
137+
}
138+
139+
private void readValues(Reader reader, ArrayList<String> values) throws IOException {
140+
for (Field field : fields) {
141+
valueBuilder.setLength(0);
142+
143+
for (int i = 0, n = field.getLength(); i < n; i++) {
144+
int c = reader.read();
145+
146+
if (c == EOF) {
147+
return;
148+
}
149+
150+
valueBuilder.append((char)c);
151+
}
152+
153+
String value = valueBuilder.toString();
154+
155+
for (int i = value.length() - 1; i >= 0; i--) {
156+
char c = value.charAt(i);
157+
158+
if (c != ' ') {
159+
value = value.substring(0, i + 1);
160+
break;
161+
}
162+
}
163+
164+
values.add(value);
165+
}
166+
167+
int c = reader.read();
168+
169+
if (c == '\r') {
170+
c = reader.read();
171+
172+
if (c != '\n') {
173+
throw new IOException("Improperly terminated record.");
174+
}
175+
}
176+
}
177+
178+
@Override
179+
public Iterator<Map<String, String>> iterator() {
180+
return iterator;
181+
}
182+
}
183+
184+
private List<Field> fields;
185+
186+
/**
187+
* Constructs a new flat file decoder.
188+
*
189+
* @param fields
190+
* The input fields.
191+
*/
192+
public FlatFileDecoder(List<Field> fields) {
193+
if (fields == null) {
194+
throw new IllegalArgumentException();
195+
}
196+
197+
this.fields = fields;
198+
}
199+
200+
/**
201+
* Reads a sequence of values from an input stream.
202+
*
203+
* @param inputStream
204+
* The input stream to read from.
205+
*
206+
* @return
207+
* A cursor over the values in the input stream.
208+
*
209+
* @throws IOException
210+
* If an exception occurs.
211+
*/
212+
public Iterable<Map<String, String>> read(InputStream inputStream) throws IOException {
213+
return read(new InputStreamReader(inputStream, Charset.forName("ISO-8859-1")));
214+
}
215+
216+
/**
217+
* Reads a sequence of values from a character stream.
218+
*
219+
* @param reader
220+
* The character stream to read from.
221+
*
222+
* @return
223+
* A cursor over the values in the character stream.
224+
*
225+
* @throws IOException
226+
* If an exception occurs.
227+
*/
228+
public Iterable<Map<String, String>> read(Reader reader) throws IOException {
229+
return new Cursor(new BufferedReader(reader), fields);
230+
}
231+
}

0 commit comments

Comments
 (0)