0
servername
|-- reports
|    |-- ABC
|    |    |-- COB02May2017
|    |    |    |-- pnlreport.pdf
|    |    |    |-- balancereport.pdf
|    |    |-- COB03May2017
|    |-- CustomerB
|    |    |-- COB02May2017
|    |    |-- COB03May2017
|    |    |    |-- balancereport.pdf 
|    |-- 01CFG
|    |    |-- COB03Sep2017

I have the above directory tree that holds my customer reports.

I have the following ReportDeliverable model:

public class ReportDeliverable {

    private String reportId;
    private String reportName;
    private String customer;
    private String format;
    private Date cobDate;
}

ReportSchedule:

public class ReportSchedule {

    private final String schedule;
    private final String reportId;
    private final String filePattern;
    private final String format;
    private final String filePath;

}

I have the following class which is responsible for providing the list of report deliverable objects:

@Service
public class FileServiceImpl implements FileService {


    @Value("${reports.source-path}")
    private String sourcePath;


    @Override
    public List<ReportDeliverable> getReportDeliverables(ReportSchedule reportSchedule) {
        List<ReportDeliverable> reportDeliverables = new ArrayList<>();
        List<Path> filesToProcess = getFilesToProcess(reportSchedule);

        filesToProcess.forEach(path -> {
            //for each path returned, extract and initialise ReportDeliverable object
            ReportDeliverable reportDeliverable = new ReportDeliverable();
            //reportDeliverable.setReportName(); > pnlreport.xls
            //reportDeliverable.setFormat(); >  > PDF
            //reportDeliverable.setCobDate(); > 26-SEP-2017
            //reportDeliverable.setClient(); > CustomerA
            //reportDeliverable.setFilePath(); > \servername\reports\CustomerA\COB26Sep2017\pnlreport.pdf

            reportDeliverables.add(reportDeliverable); 
        });

        return reportDeliverables;
    }

    public List<Path> getFilesToProcess(ReportSchedule reportSchedule) {

        String pattern = reportSchedule.getFilePattern(); //e.g. pnlreport
        String format = reportSchedule.getFormat(); // PDF

        //return full paths from here based on report criteria for COB that is T-1 (day before today). ignore the rest
        // e.g. if today is 27/09/2017
        //return -> \servername\reports\CustomerA\COB26Sep2017\pnlreport.pdf, \servername\reports\CustomerB\COB26Sep2017\pnlreport.PDF

        return path;
    }
}

Daily a directory is created with name being COB-{prior-day-date} as above directory structure. With Java 8,

  1. I need some help returning all the file paths that concern the criteria held in ReportSchedules. I have tried to explain in the comments in getFilesToProcess(ReportSchedule reportSchedule)
  2. From the paths, I need to initialize the ReportDeliverable fields, again explained in the comments getReportDeliverables(ReportSchedule reportSchedule)
M06H
  • 1,675
  • 3
  • 36
  • 76

1 Answers1

1

My understanding of your question is how to recusively go though the directory structure to find files fitting a particular pattern in directories of that are named in a way that includes a formatted date following a particular formatting rule. Here is what I came up with. There are optimizations possible but it should be a starting point.

If I understood your question wrong, you might rephrase it a bit, so I can correct my answer.

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;

public class RetrievePathsOfYesterday {

    public final static void main(String[] args) {
        String pattern = "pnlreport";
        String format = "PDF";
        String baseDir = "F:/Test";
        switch(args.length) {
        case 3:
            format = args[2];
        case 2:
            pattern = args[1];
        case 1:
            baseDir = args[0];
        }
        File root = new File(baseDir);
        File[] customerDirs = root.listFiles(file -> file.getName().toLowerCase(Locale.ENGLISH).startsWith("customer"));
        ArrayList<Path> result = new ArrayList<>();
        for (int i = 0; i < customerDirs.length; i++) {
            result.addAll(getFilesToProcess(customerDirs[i], pattern, format));
        }
        System.out.println(result);
    }

    public static List<Path> getFilesToProcess(File baseDir, String pattern, String format) {
        pattern = pattern.toLowerCase(Locale.ENGLISH);
        format = "." + format.toLowerCase(Locale.ENGLISH);
        Calendar now = Calendar.getInstance();
        now.add(Calendar.DAY_OF_YEAR, -1);
        SimpleDateFormat sdf = new SimpleDateFormat("ddMMMyyyy", Locale.ENGLISH);
        File startDir = new File(baseDir, "COB" + sdf.format(now.getTime()));
        ArrayList<Path> result = new ArrayList<>();
        getFilesToProcess(result, startDir, pattern, format);
        return result;
    }

    private static void getFilesToProcess(List<Path> resList, File baseDir, String pattern, String format) {
        System.out.println("processing " + baseDir.getAbsolutePath());
        if (!baseDir.exists()) {
            return;
        }
        File[] files = baseDir.listFiles(pathName -> {
            System.out.println("filter " + pathName.getName());
            if (pathName.isDirectory()) {
                return true;
            }
            if (!pathName.isFile()) {
                return false;
            }
            String name = pathName.getName().toLowerCase(Locale.ENGLISH);
            if (!name.startsWith(pattern)) {
                return false;
            }
            if (!name.endsWith(format)) {
                return false;
            }
            return true;
        });

        for (int i = 0; i < files.length; i++) {
            File current = files[i];
            System.out.println("Checking " + current.getAbsolutePath());
            if (current.isDirectory()) {
                getFilesToProcess(resList, current, pattern, format);
                continue;
            }
            resList.add(Paths.get(current.toURI()));
        }
    }
}

I tested this code with the following directory structure:

kimmerin@harry /cygdrive/f
$ ls -R Test
Test:
CustomerA  CustomerB

Test/CustomerA:
COB26Sep2017

Test/CustomerA/COB26Sep2017:
pnlreport.pdf

Test/CustomerB:
COB26Sep2017

Test/CustomerB/COB26Sep2017:
otherreport.PDF

If you replace Test with servername/report this should be exactly like the structure you described in your question. This is the output when starting the class with the default values:

filter pnlreport.pdf

Checking F:\Test\CustomerA\COB26Sep2017\pnlreport.pdf

processing F:\Test\CustomerB\COB26Sep2017

filter otherreport.PDF

[F:\Test\CustomerA\COB26Sep2017\pnlreport.pdf]

Lothar
  • 5,323
  • 1
  • 11
  • 27
  • From a quick glimpse at the answer, customers are unique and don't follow a pattern for their corresponding directory. – M06H Sep 27 '17 at 20:34
  • @user2781389 I added the directory structure I used for testing to the answer. – Lothar Sep 27 '17 at 20:40
  • Thanks. As customer directory level does not have a pattern in the name such as "customer" , can you update your answer to read all customer directory. Can we use Streams with Files.find() and provide maxdepth to read all customerdir? Maybe provide some optimisation scope in this answer or refactor? how to read COB date as a Date object? – M06H Sep 27 '17 at 22:38