ch.eitchnet.csvrestendpoint.marshaller.CsvDataToJsonMarshaller.java Source code

Java tutorial

Introduction

Here is the source code for ch.eitchnet.csvrestendpoint.marshaller.CsvDataToJsonMarshaller.java

Source

/*
 * Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package ch.eitchnet.csvrestendpoint.marshaller;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import ch.eitchnet.csvrestendpoint.model.CsvQuery;
import ch.eitchnet.csvrestendpoint.util.CsvFormatBuilder;
import ch.eitchnet.utils.collections.Paging;
import ch.eitchnet.utils.helper.StringHelper;

/**
 * @author Robert von Burg <eitch@eitchnet.ch>
 */
public class CsvDataToJsonMarshaller implements CsvDataMarshaller<JsonObject> {

    private int draw;
    private String query;
    private String sortBy;
    private boolean ascending;
    private int pageSize;
    private int page;

    private List<String> queryFields;
    private List<String> returnFields;

    private CSVFormat csvFormat;
    public Charset charset;

    public CsvDataToJsonMarshaller(CsvQuery query) {
        this.draw = query.getDraw();
        this.query = StringHelper.isEmpty(query.getQuery()) ? null : query.getQuery().toLowerCase();
        this.sortBy = StringHelper.isEmpty(query.getSortBy()) ? null : query.getSortBy();
        this.ascending = query.isAscending();
        this.pageSize = query.getPageSize();
        this.page = query.getPage();
        this.queryFields = Arrays.asList(query.parseQueryFields());
        this.returnFields = Arrays.asList(query.parseReturnFields());

        this.csvFormat = new CsvFormatBuilder(query).build();

        if (StringHelper.isEmpty(query.getCharset()))
            this.charset = Charset.forName("UTF-8");
        else
            this.charset = Charset.forName(query.getCharset());
    }

    @Override
    public CSVFormat getCsvFormat() {
        return this.csvFormat;
    }

    @Override
    public Charset getCharset() {
        return this.charset;
    }

    @Override
    public JsonObject marshall(CSVParser csvParser) {

        // validate any references to column names
        Map<String, Integer> headerMap = csvParser.getHeaderMap();
        validate(headerMap);

        // filter
        List<CSVRecord> allRecords = new ArrayList<>();
        long dataSetSize = 0;
        for (CSVRecord record : csvParser) {
            dataSetSize++;
            if (isSelected(headerMap, record))
                allRecords.add(record);
        }

        // sort
        if (StringHelper.isNotEmpty(sortBy)) {
            Integer columnIndex = headerMap.get(sortBy);
            if (this.ascending)
                allRecords.sort((r1, r2) -> r1.get(columnIndex).compareTo(r2.get(columnIndex)));
            else
                allRecords.sort((r1, r2) -> r2.get(columnIndex).compareTo(r1.get(columnIndex)));
        }

        // paging
        Paging<CSVRecord> paging = Paging.asPage(allRecords, this.pageSize, this.page);

        // get page
        List<CSVRecord> page = paging.getPage();

        // build JSON response
        JsonObject root = new JsonObject();
        root.addProperty("msg", "-");
        root.addProperty("draw", this.draw);
        root.addProperty("dataSetSize", dataSetSize);
        root.addProperty("nrOfElements", paging.getNrOfElements());

        if (StringHelper.isNotEmpty(sortBy))
            root.addProperty("sortBy", this.sortBy);
        root.addProperty("ascending", this.ascending);
        root.addProperty("nrOfPages", paging.getNrOfPages());
        root.addProperty("pageSize", paging.getPageSize());
        root.addProperty("page", paging.getPageToReturn());

        // prune any unwanted columns
        if (!this.returnFields.isEmpty()) {
            headerMap.keySet().retainAll(this.returnFields);
        }

        // add items
        JsonArray data = new JsonArray();
        for (CSVRecord record : page) {
            JsonObject element = new JsonObject();
            for (Entry<String, Integer> entry : headerMap.entrySet()) {
                String column = entry.getKey();
                String value = record.get(entry.getValue());
                element.addProperty(column, value);
            }
            data.add(element);
        }
        root.add("data", data);

        return root;
    }

    private void validate(Map<String, Integer> headerMap) {
        if (this.query == null)
            return;

        if (StringHelper.isNotEmpty(this.sortBy)) {
            if (!headerMap.containsKey(this.sortBy)) {
                throw new IllegalArgumentException("SortBy column " + this.sortBy + " does not exist!");
            }
        }

        if (!this.queryFields.isEmpty()) {
            for (String field : queryFields) {
                if (!headerMap.containsKey(field)) {
                    throw new IllegalArgumentException("queryField column " + field + " does not exist!");
                }
            }
        }

        if (!this.returnFields.isEmpty()) {
            for (String field : returnFields) {
                if (!headerMap.containsKey(field)) {
                    throw new IllegalArgumentException("returnField column " + field + " does not exist!");
                }
            }
        }
    }

    /**
     * Returns true if the given {@link CSVRecord} is to be selected
     * 
     * @param headerMap
     *            the map containing the column headers with the column index
     * 
     * @param record
     *            the {@link CSVRecord} to check
     * 
     * @return true if the record is to be selected, false if not
     */
    protected boolean isSelected(Map<String, Integer> headerMap, CSVRecord record) {

        if (StringHelper.isEmpty(this.query))
            return true;

        if (this.queryFields.isEmpty()) {

            // iterate all possible fields and see if the query matches
            for (String value : record) {
                if (value.toLowerCase().contains(this.query))
                    return true;
            }
        } else {

            // iterate only the query fields
            for (String queryField : this.queryFields) {
                String value = record.get(queryField);
                if (value.toLowerCase().contains(this.query))
                    return true;
            }
        }

        return false;
    }
}