public @interface Column {
String comumnName();
String format() default
"yyyy-MM-dd";
}
package processor.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Column {
String comumnName();
String format() default
"yyyy-MM-dd";
}
package processor;
import java.util.Date;
import processor.annotations.Column;
public class StockData {
private Date date;
private Double openingPrice;
private Double highestPrice;
private Double lowestPrice;
private Double closingPrice;
private Integer volume;
private Double
adjustedClosingPrice;
public StockData() {}
public Date getDate() {
return date;
}
@Column(comumnName =
"Date", format = "yyyy-mm-dd")
public void setDate(Date
date) {
this.date = date;
}
public Double
getOpeningPrice() {
return openingPrice;
}
@Column(comumnName =
"Open")
public void
setOpeningPrice(Double openingPrice) {
this.openingPrice = openingPrice;
}
public Double
getHighestPrice() {
return highestPrice;
}
@Column(comumnName =
"High")
public void
setHighestPrice(Double highestPrice) {
this.highestPrice = highestPrice;
}
public Double
getLowestPrice() {
return lowestPrice;
}
@Column(comumnName =
"Low")
public void
setLowestPrice(Double lowestPrice) {
this.lowestPrice = lowestPrice;
}
public Double
getClosingPrice() {
return closingPrice;
}
@Column(comumnName =
"Close")
public void
setClosingPrice(Double closingPrice) {
this.closingPrice = closingPrice;
}
public Integer getVolume() {
return volume;
}
@Column(comumnName =
"Volume")
public void
setVolume(Integer volume) {
this.volume = volume;
}
public Double
getAdjustedClosingPrice() {
return adjustedClosingPrice;
}
@Column(comumnName =
"Adj Close")
public void
setAdjustedClosingPrice(Double adjustedClosingPrice) {
this.adjustedClosingPrice = adjustedClosingPrice;
}
}
package processor;
import java.util.ArrayList;
import java.util.List;
public class FileProcessor<T> {
List<T>
processFile(Class className, String filename) {
List<T> result = new ArrayList<>();
return result;
}
}
package processor;
public class Main {
public static void
main(String[] args) {
FileProcessor<StockData> fileProcessor =
new FileProcessor<>();
fileProcessor.processFile(StockData.class, "ORCL.csv");
}
}
package processor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import processor.annotations.Column;
public class FileProcessor<T> {
List<T>
processFile(Class className, String filename) {
List<T> result = new ArrayList<>();
Map<String, Method> headerMap = new HashMap<>();
mapFieldNames(className, headerMap);
return result;
}
private void
mapFieldNames(Class c,
Map<String, Method> headerMap) {
for
(Method method : c.getMethods()) {
Column column = method.getAnnotation(Column.class);
if (column != null) {
headerMap.put(column.comumnName(), method);
}
}
}
}
private void mapColumnPositions(
Map<Integer,
String> headerPositionMap, String firstLine) {
StringTokenizer st = new
StringTokenizer(firstLine, ",");
int i = 0;
while (st.hasMoreTokens()) {
headerPositionMap.put(i++, st.nextToken());
}
}
private T processLine(Class className, String
line,
Map<Integer,
String> headerPositionMap,
Map<String,
Method> headerMap) throws Exception {
T t =
(T)className.newInstance();
int i = 0;
StringTokenizer st = new
StringTokenizer(line, ",");
while (st.hasMoreTokens()) {
String columnName = headerPositionMap.get(i);
Method setter = headerMap.get(columnName);
Parameter parameter = setter.getParameters()[0];
if
(parameter.getType().equals(Date.class)) {
Column column = setter.getAnnotation(Column.class);
DateFormat df = new SimpleDateFormat(column.format());
setter.invoke(t, df.parse(st.nextToken()));
}
else if (parameter.getType().equals(Double.class)) {
setter.invoke(t, Double.valueOf(st.nextToken()));
}
else if (parameter.getType().equals(Integer.class)) {
setter.invoke(t, Integer.valueOf(st.nextToken()));
}
else {
// assume it accepts a String
setter.invoke(t, st.nextToken());
}
i++;
}
return t;
}
package processor;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.annotation.Annotation;
import
java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import processor.annotations.Column;
public class FileProcessor<T> {
List<T>
processFile(Class className, String filename) {
List<T> result = new ArrayList<>();
Map<String, Method> headerMap = new HashMap<>();
Map<Integer, String> headerPositionMap = new HashMap<>();
mapFieldNames(className, headerMap);
Path
path = Paths.get(filename);
try
{
Files.lines(path).limit(1).forEach(
s -> mapColumnPositions(headerPositionMap, s));
Files.lines(path).skip(1).forEach(s -> {
try {
result.add(processLine(className,
s, headerPositionMap, headerMap));
} catch (Exception e) {
Logger.getLogger(FileProcessor.class.getName()).
log(Level.SEVERE, "Error occurred", e);
}
});
}
catch (IOException ex) {}
return result;
}
private void
mapFieldNames(Class c, Map<String, Method> headerMap) {
for
(Method method : c.getMethods()) {
Column column = method.getAnnotation(Column.class);
if (column != null) {
headerMap.put(column.comumnName(), method);
}
}
}
private T processLine(Class
className, String line, Map<Integer, String> headerPositionMap,
Map<String, Method> headerMap) throws Exception {
T t
= (T)className.newInstance();
int
i = 0;
StringTokenizer st =
new StringTokenizer(line, ",");
while (st.hasMoreTokens()) {
String columnName = headerPositionMap.get(i);
Method setter = headerMap.get(columnName);
Parameter parameter = setter.getParameters()[0];
if (parameter.getType().equals(Date.class)) {
Column column = setter.getAnnotation(Column.class);
DateFormat df =
new SimpleDateFormat(column.format());
setter.invoke(t, df.parse(st.nextToken()));
} else if (parameter.getType().equals(Double.class)) {
setter.invoke(t, Double.valueOf(st.nextToken()));
} else if (parameter.getType().equals(Integer.class)) {
setter.invoke(t, Integer.valueOf(st.nextToken()));
} else {
// assume it accepts a String
setter.invoke(t, st.nextToken());
}
i++;
}
return t;
}
private void
mapColumnPositions(Map<Integer, String> headerPositionMap, String
firstLine) {
StringTokenizer st = new StringTokenizer(firstLine, ",");
int
i = 0;
while (st.hasMoreTokens()) {
headerPositionMap.put(i++, st.nextToken());
}
}
}
package processor;
import java.util.List;
import java.util.OptionalDouble;
import java.util.OptionalInt;
public class Main {
public static void
main(String[] args) {
FileProcessor<StockData> fileProcessor =
new FileProcessor<>();
List<StockData> data = fileProcessor.processFile(
StockData.class, "ORCL.csv");
//
find the maximum volume
OptionalInt resultVolume = data.stream().
mapToInt(sd -> sd.getVolume()).max();
//
find the maximum difference between the opening price
//
and the closing price
OptionalDouble resultPrice = data.stream().mapToDouble(
sd -> sd.getClosingPrice()-sd.getOpeningPrice()).max();
//
find the minimum opening price
OptionalDouble lowestPrice = data.stream().mapToDouble(
sd -> sd.getOpeningPrice()).min();
//
find the maximum opening price
OptionalDouble highestPrice =
data.stream().mapToDouble(
sd -> sd.getOpeningPrice()).max();
System.out.println("Highest volume: "+
resultVolume.getAsInt());
System.out.println("Highest price change : "+
resultPrice.getAsDouble());
System.out.println("Lowest price : "+
lowestPrice.getAsDouble());
System.out.println("Highest price : "+
highestPrice.getAsDouble());
}
}