How to get specific data from a CSV file - java

I have a very big CSV file, I have managed to put all this into an ArrayList using Scanner
Path filepath = Paths.get("./data.csv");
try{
Scanner InputStream = new Scanner(filepath);
while (InputStream.hasNext()){
wholefile.add(String.valueOf(InputStream.next()));
} InputStream.close();
System.out.println(wholefile);
} catch (IOException e) {
e.printStackTrace();
}
}
and my array looks like this :
wholefile = [id,property, address,first_name,last_name,email,Owner, contact, address,Price,Date, sold, 1,94032, Mockingbird, Alley,Brander,Verillo,bverillo0#sogou.com,,435587.57,, 2,293, Haas, Lane,Maxy,Reynalds...........]
Here is a screenshot of the csv file in excel
https://plus.google.com/photos/photo/115135191238195349859/6559552907258825106?authkey=CIu-hovf5pj29gE
There are some things that I would like to do with this data but I am confused what methods I need to write:
Get a property record by ID
Get a list of n number of top priced properties
Total sales for a month.
any help or guidance would be much appreciated, I'm not sure if I'm goign about this the right way
https://plus.google.com/photos/photo/115135191238195349859/6559637333893665186

Don't waste time by reinventing the wheel.
I suggest to use Apache Commons CSV library to manipulate .csv files.
you can find official doc here.
And some examples here.

I had to roll out a custom CSV parser for some proof of concept we were trying to do and I think you could re purpose it here:
CSVReader.java
public class CSVReader implements Iterable<CSVRow> {
private List<String> _data;
private int _itPos = 0;
private int _skip = 0;
private FileIterator _it;
private boolean _hasTrailingComma = false;
public CSVReader(Path path, boolean hasTrailingComma) throws IOException {
this(Files.readAllLines(path), hasTrailingComma);
}
public CSVReader(Path path) throws IOException {
this(path, false);
}
public CSVReader(List<String> data, boolean hasTrailingComma) {
_data = data;
_it = new FileIterator();
_hasTrailingComma = hasTrailingComma;
}
public CSVReader(List<String> data) {
this(data, false);
}
public CSVRow getHeaders() {
return new CSVRow(_data.get(0), _hasTrailingComma);
}
public void skip(int rows) {
_skip = rows;
}
#Override
public Iterator<CSVRow> iterator() {
_itPos = _skip;
return _it;
}
private class FileIterator implements Iterator<CSVRow> {
#Override
public boolean hasNext() {
return _itPos < _data.size();
}
#Override
public CSVRow next() {
if (_itPos == _data.size()) {
throw new NoSuchElementException();
}
return new CSVRow(_data.get(_itPos++), _hasTrailingComma);
}
}
}
CSVRow.java
public class CSVRow implements Iterable<String> {
private String[] _data;
private int _itPos = 0;
private int _skip = 0;
private RowIterator _it = null;
private int _actualLength = 0;
public CSVRow(String row, boolean trailingComma) {
// Minor hack
// in case the data doesn't end in commas
// we check for the last character and add
// a comma. Ideally, the input file should be fixed;
if(trailingComma && !row.endsWith(",")) {
row += ",";
}
_data = row.split("\\s*,\\s*", -1);
_actualLength = trailingComma ? _data.length - 1 : _data.length;
_it = new RowIterator();
}
public CSVRow(String row) {
this(row, false);
}
public void skip(int cells) {
_skip = cells;
}
#Override
public Iterator<String> iterator() {
_itPos = _skip;
return _it;
}
public String[] toArray() {
return Arrays.copyOf(_data, _actualLength);
}
private class RowIterator implements Iterator<String> {
#Override
public boolean hasNext() {
return _itPos < _actualLength;
}
#Override
public String next() {
if (_itPos == _actualLength) {
throw new NoSuchElementException();
}
return _data[_itPos++];
}
}
}
Usage
public static void main(String[] args) {
Path filepath = Paths.get("./data.csv");
CSVReader reader = new CSVReader(filepath);
for (CSVRow row : reader) {
for (String str : row) {
System.out.printf("%s ", str);
}
System.out.println();
}
}
Now it will be useful to model each row as an object so that you can do stuff with it in Java. You can define a class Property that models each row
public class Property {
private int id;
private String address;
private String firstName;
private String lastName;
private String email;
private String ownerContactAddress;
private BigDecimal price;
private java.sql.Date dateSold;
public Property() {
}
// Setters and getters
public long getId() {
return this.id;
}
public void setId(String id) {
this.id = Long.parseLong(id);
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
// TODO: setter/getters for firstName, lastName, email, ownerContactAddress
public BigDecimal getPrice() {
return this.price;
}
public void setPrice(String price, Locale locale) throws ParseException {
NumberFormat format = NumberFormat.getNumberInstance(locale);
if (format instanceof DecimalFormat) {
((DecimalFormat) format).setParseBigDecimal(true);
}
this.price = (BigDecimal) format.parse(amount.replaceAll("[^\\d.,]",""));
}
public java.sql.Date getDateSold() {
return this.dateSold;
}
public void setDateSold(String date, String format) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
this.dateSold = new Date(sdf.parse(date).getTime());
}
}
Bringing everything together (Not tested)
public static void main(String[] args) {
// Collection to store properties
// You could also write a class to wrap this
// map along with the methods you need to implement
// Say PropertyTable {
// private Map<Long, Property> properties ...
// Property getPropertyById(long id);
// getHighestPriced() // sort the map by price
// }
Map<Long, Property> properties = new HashMap<>();
Path filepath = Paths.get("./data.csv");
CSVReader reader = new CSVReader(filepath);
for (CSVRow row : reader) {
Iterator<String> it = row.iterator();
Property p = new Property();
p.setId(it.next());
p.setAddress(it.next());
// ... set the remaining properties
p.setPrice(it.next(), new Locale("en", "GB"));
p.seDateSold(it.next(), "MM/dd/yyyy");
properties.put(p.getId(), p);
}
// At this point, you should have all the properties read
// let's try to get property with id 5
Property prop = properties.get(5L);
}
I hope this helps.

With an ArrayList of Strings will have a bad Performance at time of doing what do you want.
First Create an Object that Match your CVS Header. Then at time of reading the File start adding to an ArrayList of the Object you created, and for sorting, search and a Total sales just make a stream over the ArrayList.

Related

How to allow Introspector.getBeans.getPropertyDescriptors() result in insertion order rather alphabetical order

I run the following to get Bean's fields and its values but I get the alphabetical order of property names.
Is there a way to get the order in which they can maintain the order in which bean has?
My Bean
#Component
public class FeedFile {
private String pkey;
private String omsOrderId;
private String auctTitl;
private String byrCntryId;
private String lstgCurncyIsoCodeName;
private String transSiteId;
public String getPkey() {
return pkey;
}
public void setPkey(String pkey) {
this.pkey = pkey;
}
public String getOmsOrderId() {
return omsOrderId;
}
public void setOmsOrderId(String omsOrderId) {
this.omsOrderId = omsOrderId;
}
public String getAuctTitl() {
return auctTitl;
}
public void setAuctTitl(String auctTitl) {
this.auctTitl = auctTitl;
}
public String getByrCntryId() {
return byrCntryId;
}
public void setByrCntryId(String byrCntryId) {
this.byrCntryId = byrCntryId;
}
public String getLstgCurncyIsoCodeName() {
return lstgCurncyIsoCodeName;
}
public void setLstgCurncyIsoCodeName(String lstgCurncyIsoCodeName) {
this.lstgCurncyIsoCodeName = lstgCurncyIsoCodeName;
}
public String getTransSiteId() {
return transSiteId;
}
public void setTransSiteId(String transSiteId) {
this.transSiteId = transSiteId;
}
Introspector code. Using StringBuilder to verify the order of Introspector.getBeans.getPropertyDescriptors() that returns in alphabetical order. It isn't related to hashmap random order in the result.
StringBuilder sb = new StringBuilder();
Map<String, String> result = new HashMap<>();
for (PropertyDescriptor pd : Introspector.getBeanInfo(file.getClass()).getPropertyDescriptors()) {
String name = pd.getName();
Object value = pd.getReadMethod().invoke(file);
if ("class".equals(name)) continue;
sb.append(name);
sb.append(":");
sb.append(value);
sb.append(",");
result.put(name, String.valueOf(value));
}
Actual Output of the above in String Builder sb:
sb.toString()="auctTitl:Hello,byrCntryId:123,lstgCurncyIsoCodeName:USD,omsOrderId:234,pkey:567, transSiteId:987,";
Expected Output should be in the order of declaration of above bean FeedFile:
sb.toString()="pkey:567,omsOrderId:234,auctTitl:Hello,byrCntryId:123,lstgCurncyIsoCodeName:USD,transSiteId:987,";
I googled and found that Introspector only returns in alphabetical order. Is there any way I can get the expected output.
I changed my above approach and this simplified it a lot.
I actually found a better way of doing this using PrintWriter, where my bean gets directly added to csv by overriding toString() in java bean. Here is what I did:
public void writeToCsv(List<Sample> sampleList, String header) throws IOException {
PrintWriter writer = new PrintWriter("filepath/demo/sample.csv");
writer.println(header);
for (Sample sample : sampleList) {
writer.println(sample.toString());
}
writer.close();
}
Bean
class Sample {
private String id;
private String type;
private String name;
private int value;
// getter-setter
#Override
public String toString(){
StringBuilder dataBuilder = new StringBuilder();
appendFieldValue(dataBuilder, id);
appendFieldValue(dataBuilder, type);
appendFieldValue(dataBuilder, name);
appendFieldValue(dataBuilder, value);
return dataBuilder.toString();
}
private void appendFieldValue(StringBuilder dataBuilder, String fieldValue) {
if(fieldValue != null) {
dataBuilder.append(fieldValue).append(",");
} else {
dataBuilder.append("").append(",");
}
}
}

Java: Arraylist out of bounds when processing file [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 2 years ago.
I am trying to create an ArrayList that reads a .csv file, processes the data into an ArrayList, and then print the list out.
My code so far.
The BankRecords class
import java.io.*;
import java.util.*;
public class BankRecords
{
String sex, region, married, save_act, current_act, mortgage, pep;
int children;
double income;
private String id;
private int age;
public BankRecords(String gender, String area, String marriage, String SaveAccount, String CurrentAccount, String HouseBill, String pepp, int minors, double paycheck, String identification, int years)
{
this.sex = gender;
this.region = area;
this.married = marriage;
this.save_act = SaveAccount;
this.current_act = CurrentAccount;
this.mortgage = HouseBill;
this.pep = pepp;
this.children = minors;
this.income = paycheck;
this.id = identification;
this.age = years;
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getSex()
{
return sex;
}
public void setSex(String sex)
{
this.sex = sex;
}
public String getRegion()
{
return region;
}
public void setRegion(String region)
{
this.region = region;
}
public String getMarried()
{
return married;
}
public void setMarried(String married)
{
this.married = married;
}
public String getSave_act()
{
return save_act;
}
public void setSave_act(String save_act)
{
this.save_act = save_act;
}
public String getCurrent_act()
{
return current_act;
}
public void setCurrent_act(String current_act)
{
this.current_act = current_act;
}
public String getMortgage()
{
return mortgage;
}
public void setMortgage(String mortgage)
{
this.mortgage = mortgage;
}
public String getPep()
{
return pep;
}
public void setPep(String pep)
{
this.pep = pep;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public int getChildren()
{
return children;
}
public void setChildren(int children)
{
this.children = children;
}
public double getIncome()
{
return income;
}
public void setIncome(double income)
{
this.income = income;
}
}
The Client abstract class
import java.io.*;
import java.util.*;
public abstract class Client
{
static ArrayList<List<String>> BankArray = new ArrayList<>(25);
static BankRecords robjs[] = new BankRecords[600];
public static void readData()
{
try
{
BufferedReader br;
String filepath = "C:\\Users\\eclipse-workspace\\Bank_Account\\src\\bank-Detail.csv";
br = new BufferedReader(new FileReader (new File(filepath)));
String line;
while ((line = br.readLine()) != null)
{
BankArray.add(Arrays.asList(line.split(",")));
}
}
catch (Exception e)
{
e.printStackTrace();
}
processData();
}
public static void processData()
{
int idx=0;
for (List<String> rowData: BankArray)
{
robjs[idx] = new BankRecords(null, null, null, null, null, null, null, idx, idx, null, idx);
robjs[idx].setId(rowData.get(0));
robjs[idx].setAge(Integer.parseInt(rowData.get(1)));
idx++;
}
printData();
}
public static void printData()
{
System.out.println("ID\tAGE\tSEX\tREGION\tINCOME\tMORTGAGE");
int final_record = 24;
for (int i = 0; i < final_record; i++)
{
System.out.println(BankArray.get(i) + "\t ");
}
}
}
The BankRecordsTest class (extends Client)
import java.util.*;
import java.io.*;
public class BankRecordsTest extends Client
{
public static void main(String args [])
{
readData();
}
}
The error
And here is the error.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at java.util.Arrays$ArrayList.get(Unknown Source)
at Client.processData(Client.java:33)
at Client.readData(Client.java:24)
at BankRecordsTest.main(BankRecordsTest.java:7)
I'm not sure what the index problem is. Do note that if you run the ReadData() and PrintData() functions separately, the code runs fine but the ProcessData() method causes issues.
I think your data is likely not clean and you are making assumptions about the length of your array. The error you are getting stems from this line:
robjs[idx].setAge(Integer.parseInt(rowData.get(1)));
Clearly, rowData doesn't have 2 items (or more). This is why you are getting ArrayIndexOutOfBoundsException. So you want to check where your variable was initialized. You quickly realize it comes from
for (List<String> rowData: BankArray)
So then, the following question is where BankArray gets initialized. That happens in 2 places. First of all
static ArrayList<List<String>> BankArray = new ArrayList<>(25);
You are creating an empty list. So far so good. Note that you don't need to (and therefore shouldn't) initialize with a size. Lists are not like arrays insofar as they can easily grow and you don't need to give their size upfront.
The second place is
BankArray.add(Arrays.asList(line.split(",")));
This is likely where the issue comes from. Your row variable contains the results of Arrays.asList(line.split(",")). So the size of that list depends on the number of commas in that string you are reading. If you don't have any commas, then the size will be 1 (the value of the string itself). And that's what leads me to concluding you have a data quality issue.
What you should really do is add a check in your for (List<String> rowData: BankArray) loop. If for instance, you expect 2 fields, you could write something along the lines of:
if (rowData.size()<2){
throw new Exception("hmmm there's been a kerfuffle');
}
HTH

Java - Type Mismatch: Cannot Convert From Element type String[] to List<String>

I'm unfamiliar with getters and setters (and basically just Java) but I have to use them for this assignment, so if I did anything wrong with those please tell me.
The more important issue is the error that I am getting on my method. The word for word instructions from my assignment for the particular method I'm working on are:
Your processData() method should take all the record data from your ArrayList and add the data into each of your instance fields via your setters.
But I keep getting an error that says:
Type mismatch: cannot convert from element type String[] to List
On the line that says "for (List<String> rowData: content)" on the word content.
Thank you very much for any help you can give me.
My code so far:
public abstract class Client {
String file = "bank-Detail.csv";
ArrayList<String[]> bank = new ArrayList<>();
static Client o[] = new Client[12];
public Client(String file) {
this.file = file;
}
private String ID;
private String Age;
private String Sex;
private String Region;
private String Income;
private String Married;
private String Children;
private String Car;
private String Save_Act;
private String Current_Act;
private String Mortgage;
private String Pep;
public List<String[]> readData() throws IOException {
//initialize variable
int count = 0;
//name file
String file = "bank-Detail.txt";
//make array list
List<String[]> content = new ArrayList<>();
//trycatch for exceptions
try {
//file reader
BufferedReader br = new BufferedReader(new FileReader(file));
//string to add lines to
String line = "";
while ((line = br.readLine()) != null) {
content.add(line.split(","));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
processData(content);
return content;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getAge() {
return Age;
}
public void setAge(String age) {
this.Age = age;
}
public String getSex() {
return Sex;
}
public void setSex(String sex) {
Sex = sex;
}
public String getRegion() {
return Region;
}
public void setRegion(String region) {
Region = region;
}
public String getIncome() {
return Income;
}
public void setIncome(String income) {
Income = income;
}
public String getMarried() {
return Married;
}
public void setMarried(String married) {
Married = married;
}
public String getChildren() {
return Children;
}
public void setChildren(String children) {
Children = children;
}
public String getCar() {
return Car;
}
public void setCar(String car) {
Car = car;
}
public String getSave_Act() {
return Save_Act;
}
public void setSave_Act(String save_Act) {
Save_Act = save_Act;
}
public String getCurrent_Act() {
return Current_Act;
}
public void setCurrent_Act(String current_Act) {
this.Current_Act = current_Act;
}
public String getMortgage() {
return Mortgage;
}
public void setMortgage(String mortgage) {
this.Mortgage = mortgage;
}
public String getPep() {
return Pep;
}
public void setPep(String pep) {
Pep = pep;
}
public String toString() {
return "[ID = " + ", age=";
/// ect....
}
public void processData(List<String[]> content) {
int index = 0;
for (List<String> rowData : content) {
//initialize array of objects
//o[index] = new Client();
//use setters to populate your array of objects
o[index].setID(rowData.get(0));
o[index].setAge(rowData.get(1));
o[index].setRegion(rowData.get(3));
o[index].setSex(rowData.get(2));
o[index].setIncome(rowData.get(4));
o[index].setMarried(rowData.get(5));
o[index].setChildren(rowData.get(6));
o[index].setCar(rowData.get(7));
o[index].setSave_Act(rowData.get(8));
o[index].setCurrent_Act(rowData.get(9));
o[index].setMortgage(rowData.get(10));
o[index].setPep(rowData.get(11));
System.out.println(rowData);
index++;
}
}
public void printData() {
}
}
The problem is in the processData method. The type of content is List<String[]>. So when you try to loop this list, each element is a String array, not List. Also, since each element in your list is a String array, you can access the elements of each of the String Array elements of the list by using the normal array square brackets, instead of get method of List. Try the following fix:
public void processData(List<String[]> content) {
int index=0;
for (String[] rowData: content){
//initialize array of objects
//o[index] = new Client();
//use setters to populate your array of objects
o[index].setID(rowData[0]);
o[index].setAge(rowData[1]);
o[index].setRegion(rowData[3]);
o[index].setSex(rowData[2]);
o[index].setIncome(rowData[4]);
o[index].setMarried(rowData[5]);
o[index].setChildren(rowData[6]);
o[index].setCar(rowData[7]);
o[index].setSave_Act(rowData[8]);
o[index].setCurrent_Act(rowData[9]);
o[index].setMortgage(rowData[10]);
o[index].setPep(rowData[11]);
System.out.println(rowData);
index++;
}
}
As your error hints at... content is a List<String[]>, so it contains String[] elements, not List<String> elements.
If your end goal is a list of Client objects, just make the method List<Client> readData() instead.
List<Client> clients = new ArrayList<Client>();
BufferedReader br = null;
try {
//file reader
br = new BufferedReader(new FileReader(file));
//string to add lines to
String line = "";
Client c = null;
while ((line = br.readLine()) != null) {
c = new Client();
String[] rowData = line.split(",");
c.setID(rowData.get(0));
...
clients.add(c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (br != null) br.close();
} catch (Exception e) {}
}
return clients;

How does one pass a class through an array and then fill the array with a txt document

So... My goal here to run this class through an array then fill the array with a .txt document with 43 instances which I will then take user data and compare the two to find an ideal match. I should note that this is for a seating plan -
The text document looks like so -
01 STANDARD True False True F False
public class Seat {
private String eMail = "";
private int number;
private String type;
private boolean window;
private boolean aisle;
private boolean table;
private String f;
private String b;
private boolean ease;
public Seat(int number, String type, boolean window, boolean aisle, boolean table, String f, String b, boolean ease) {
this.number = number;
this.type = type;
this.window = window;
this.aisle = aisle;
this.table = table;
this.f = f;
this.b = b;
this.ease = ease;
}
public String geteMail() {
return eMail;
}
public void seteMail(String eMail) {
this.eMail = eMail;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isWindow() {
return window;
}
public void setWindow(boolean window) {
this.window = window;
}
public boolean isAisle() {
return aisle;
}
public void setAisle(boolean aisle) {
this.aisle = aisle;
}
public boolean isTable() {
return table;
}
public void setTable(boolean table) {
this.table = table;
}
public String getF() {
return f;
}
public void setF(String f) {
this.f = f;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public boolean isEase() {
return ease;
}
public void setEase(boolean ease) {
this.ease = ease;
}
}
public class Driver {
static Scanner S = new Scanner(System.in);
public static void main(String[] args) throws FileNotFoundException {
Scanner inFile = new Scanner(new File("//Users//Mike//Desktop//Seats-2.txt"));
String reservation = inFile.nextLine();
Seat seat [] = new Seat [43];
//while (inFile.hasNextLine()){
//for(int i = 0; i <= reservation.length(); i++){
//System.out.println(reservation.toString(seat));
//}
//}
I've tried methods such as equals(reservation.toString()) how ever these won't work due to the array being built from the Class Seat.
Any guidance will be very helpful.
I'm not looking for easy fix, just some guidance on where to look.
Thank you
If the text file is small, let's just read it whole in a String
public static String ReadWholeFile(String filename) throws IOException
{
final File file = new File(filename);
final FileInputStream fis = new FileInputStream(file);
final byte[] data = new byte[(int)file.length()];
fis.read(data);
fis.close();
return new String(data, "UTF-8");
}
And then parse line by line, converting in Seats
public List<Seat> getSeats(String filename) throws IOException {
final String[] lines = ReadWholeFile(filename).split("\n");
final List<Seat> ret = new ArrayList<Seat>();
for (int i=0; i<lines.length; i++)
try {
final String[] parts = lines[i].split("\\s"); // split on whitespaces
final int num = Integer.parseInt(parts[0]);
ret.add(new Seat(num, parts[1], isTrue(parts[2]), isTrue(parts[3]), isTrue(parts[4]), isTrue(parts[5]), isTrue(parts[6]));
}
catch (Exception e) { /* whatever */ }
return ret;
}
Strings that mean true are "T", "true", ...? If that's the case:
public static isTrue(String x) {
return x.startsWith("T") || x.startsWith("t");
}
if you really don't want to read the whole file, you could go with:
public static List<Seat> getSeats2(String filename) {
final List<Seat> ret = new ArrayList<Seat>();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(filename));
String line;
while (line = br.readLine()) {
final String[] parts = line.split("\\s"); // split on whitespaces
// as above
}
}
catch (Exception e) { /* handle errors */ }
finally {
if (br != null)
try { br.close(); }
catch (Exception e) {}
}
return res;
}

Sorting int field of the wrapper class spring

I have a Navigation class where I am dynamically creating the navigation I am having two tables folder(it is directory that contains files) and content(it is like files or pages that will render the content on the public site). I have created a Navigation class in which I am having a wrapper class for merging the fields of content into the folder. I have tried using #OrderBy and #OrderColumn but I came to know that it will only work with collections.
List<Folder> folder = folderRepository.findAllByNavDepthLessThanOrderByNavDepthAsc(3);
here I am sorting it with navDepth(this column belongs to Folder entity) I also want to sort it with navOrder(this column belongs to Content entity)
#Service
public class NavigationService {
#Qualifier("jdbcMySQL")
private JdbcTemplate jdbcTemplate;
private FolderRepository folderRepository;
private FolderService folderService;
#Autowired
public NavigationService(JdbcTemplate jdbcTemplate,
FolderRepository folderRepository,
FolderService folderService) {
this.jdbcTemplate = jdbcTemplate;
this.folderRepository = folderRepository;
this.folderService = folderService;
}
#Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public Map<String, NavigationItem> navigationItems() {
// TODO: // CROSS cutting AOP springs
// TODO: http://docs.spring.io/spring/docs/4.2.0.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#aop
List<Folder> folder = folderRepository.findAllByNavDepthLessThanOrderByNavDepthAsc(3);
// List<Folder> folder = folderService.navigation();
Map<String, NavigationItem> navItems = new LinkedHashMap<String, NavigationService.NavigationItem>();
for (int i = 0; i < folder.size(); i++) {
NavigationItem ni = new NavigationItem();
ni.setNavDepth((int) (folder.get(i).getNavDepth()));
ni.setFileNamePath(folder.get(i).getDirectoryPath());
ni.setFilepath(folder.get(i).getDirectoryPath());
ni.setChildren(folder.get(i).getContent());
for (int k = 0; k < folder.size(); k++) {
if(folder.get(i).getId() == folder.get(k).getParentId()) {
ni.addSubFolder(folder.get(k));
System.out.println(folder.get(i).getTitle());
System.out.println(folder.get(k));
System.out.println("---!!!!!!________----------!!!!!!!!");
}
}
navItems.put(folder.get(i).getTitle(), ni);
}
return navItems;
}
public class NavigationItem {
private long id;
private long parentId;
private String title;
private String fileName;
private String fileNamePath;
private int navDepth;
private int navOrder;
private String parentFileName;
private String filePath;
private String folderName;
#OrderColumn(name="navOrder ASC")
private List<Content> children = new ArrayList();
private ArrayList<Folder> subFolder = new ArrayList();
public void setSubFolder(ArrayList<Folder> subFolder) {
this.subFolder = subFolder;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFolderName() {
return folderName;
}
public void setFolderName(String folderName) {
this.folderName = folderName;
}
public ArrayList<Folder> getSubFolder() {
return subFolder;
}
public void addSubFolder(Folder subFolder) {
this.subFolder.add(subFolder);
}
public void setChildren(List<Content> list) {
this.children = list;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getParentId() {
return parentId;
}
public void setParentId(long parentId) {
this.parentId = parentId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileNamePath() {
return fileNamePath;
}
public void setFileNamePath(String fileNamePath) {
this.fileNamePath = fileNamePath;
}
public long getNavDepth() {
return navDepth;
}
public void setNavDepth(int navDepth) {
this.navDepth = navDepth;
}
public long getNavOrder() {
return navOrder;
}
public void setNavOrder(int navOrder) {
this.navOrder = navOrder;
}
public String getParentFileName() {
return parentFileName;
}
public void setParentFileName(String parentFileName) {
this.parentFileName = parentFileName;
}
public List<Content> getChildren() {
return children;
}
public void addChild(Content child) {
children.add(child);
}
public String getFilepath() {
return filePath;
}
public void setFilepath(String filePath) {
this.filePath = filePath;
}
}
}
Use a Comparator<NavigationItem> and pass that to Collections.sort() or similar methods.
The comparator might look like this:
class NavComparator implements Comparator<NavigationItem> {
int specialValueNoChildren = -1; //assuming nav_order is always 0 or greater
int compare(NavigationItem o1, NavigationItem o2) {
int max1 = getMaxNavOrder( o1 );
int max2 = getMaxNavOrder( o2 );
return Integer.compare( max1, max2 );
}
int getMaxNavOrder( NavigationItem ni ) {
int max = specialValueNoChildren;
for( Content child : ni.getChildren() ) {
max = Math.max(max, child.getNavOrder());
}
return max;
}
}
Here the maximum nav order of all children is selected with -1 being the special case of no children. Then the items are compared by their respective children's maximum nav order.
If you need a different order change that accordingly, e.g. by reversing max1 and max2 or by getting the lowest nav order of the children etc.

Categories