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());

    }

}