org.cyclop.service.exporter.intern.CsvQueryResultExporterImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.cyclop.service.exporter.intern.CsvQueryResultExporterImpl.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.cyclop.service.exporter.intern;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.cyclop.common.AppConfig;
import org.cyclop.model.CqlColumnValue;
import org.cyclop.model.CqlDataType;
import org.cyclop.model.CqlExtendedColumnName;
import org.cyclop.model.CqlQuery;
import org.cyclop.model.CqlQueryResult;
import org.cyclop.model.exception.ServiceException;
import org.cyclop.service.cassandra.QueryService;
import org.cyclop.service.converter.DataConverter;
import org.cyclop.service.converter.DataExtractor;
import org.cyclop.service.exporter.CsvQueryResultExporter;
import org.cyclop.validation.EnableValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Row;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

/** @author Maciej Miklas */
@Named
@EnableValidation
public class CsvQueryResultExporterImpl implements CsvQueryResultExporter {

    private final static Logger LOG = LoggerFactory.getLogger(CsvQueryResultExporterImpl.class);

    @Inject
    private DataExtractor extractor;

    @Inject
    private DataConverter converter;

    @Inject
    private AppConfig.QueryExport conf;

    @Inject
    private QueryService queryService;

    @Override
    public String exportAsCsv(CqlQuery query) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        exportAsCsv(query, bos);
        try {
            String resStr = new String(bos.toByteArray(), conf.encoding);
            return resStr;
        } catch (UnsupportedEncodingException e) {
            throw new ServiceException(
                    "Encoding: " + conf.encoding + " caused error during export: " + e.getMessage(), e);
        }
    }

    @Override
    public void exportAsCsv(CqlQuery query, OutputStream output) {
        LOG.debug("Starting CSV export for {}", query);

        PrintWriter out = new PrintWriter(output);
        CqlQueryResult result = queryService.execute(query, false);

        // header
        appendHeader(query, out);

        // column names
        ImmutableList<CqlExtendedColumnName> columns = result.rowMetadata.columns;
        appendColumns(out, columns);
        out.append(conf.separatorRow);

        // content
        for (Row row : result) {
            appendRow(out, row, columns);
            out.append(conf.separatorRow);
        }

        out.flush();
        out.close();
    }

    private void appendRow(PrintWriter out, Row row, List<CqlExtendedColumnName> cols) {
        LOG.debug("Appending next row");
        Iterator<CqlExtendedColumnName> it = cols.iterator();
        while (it.hasNext()) {
            CqlExtendedColumnName column = it.next();
            CqlDataType dataType = column.dataType;

            if (dataType.name == DataType.Name.SET || dataType.name == DataType.Name.LIST) {
                appendCollection(out, row, column);

            } else if (dataType.name == DataType.Name.MAP) {
                appendMap(out, row, column);
            } else {
                appendSingleValue(out, row, column);
            }

            if (it.hasNext()) {
                out.append(conf.separatorColumn);
            }
        }
    }

    private void appendMap(PrintWriter out, Row row, CqlExtendedColumnName column) {
        ImmutableSet<Map.Entry<CqlColumnValue, CqlColumnValue>> displayMap = extractor.extractMap(row, column)
                .entrySet();
        Iterator<Map.Entry<CqlColumnValue, CqlColumnValue>> it = displayMap.iterator();

        LOG.trace("Appending: {}", displayMap);

        StringBuilder mapBuf = new StringBuilder();
        while (it.hasNext()) {
            Map.Entry<CqlColumnValue, CqlColumnValue> entry = it.next();

            CqlColumnValue key = entry.getKey();
            String keyText = esc(converter.convert(key.value));
            mapBuf.append(keyText);

            mapBuf.append(conf.separatorMap);

            CqlColumnValue val = entry.getValue();
            String valText = esc(converter.convert(val.value));
            mapBuf.append(valText);

            if (it.hasNext()) {
                mapBuf.append(conf.separatorList);
            }
        }

        String mapVal = esc(mapBuf.toString());
        LOG.trace("Appended map: {}", mapVal);
        out.append(mapVal);
    }

    private void appendCollection(PrintWriter out, Row row, CqlExtendedColumnName column) {
        ImmutableList<CqlColumnValue> content = extractor.extractCollection(row, column);
        LOG.trace("Appending {}", content);
        Iterator<CqlColumnValue> contentIt = content.iterator();
        StringBuilder listBuild = new StringBuilder();
        while (contentIt.hasNext()) {
            CqlColumnValue cqlColumnValue = contentIt.next();
            String valText = esc(converter.convert(cqlColumnValue.value));
            listBuild.append(valText);
            if (contentIt.hasNext()) {
                listBuild.append(conf.separatorList);
            }
        }
        String colVal = esc(listBuild.toString());
        LOG.trace("Append collection: {}", colVal);
        out.append(colVal);
    }

    private void appendSingleValue(PrintWriter out, Row row, CqlExtendedColumnName column) {
        CqlColumnValue cqlColumnValue = extractor.extractSingleValue(row, column);
        String valText = esc(converter.convert(cqlColumnValue.value));
        LOG.trace("Append single value: {}", valText);
        out.append(valText);
    }

    private void appendHeader(CqlQuery query, PrintWriter out) {
        String headerVal = prep(query.part);
        LOG.trace("Append header: {}", headerVal);
        out.append(headerVal);
        out.append(conf.separatorQuery);
    }

    private void appendColumns(PrintWriter out, List<CqlExtendedColumnName> columns) {
        if (columns.isEmpty()) {
            return;
        }

        LOG.trace("Appending {}", columns);

        Iterator<CqlExtendedColumnName> commonColsIt = columns.iterator();
        while (commonColsIt.hasNext()) {
            CqlExtendedColumnName next = commonColsIt.next();
            out.append(prep(esc(next.toDisplayString())));

            if (commonColsIt.hasNext()) {
                out.append(conf.separatorColumn);
            }
        }
    }

    private String prep(String val) {
        if (val == null) {
            val = "";
        }
        if (conf.trim) {
            val = val.trim();
        }

        if (conf.removeCrChars) {
            val = val.replaceAll("[\n\r]", "");
        }

        return val;
    }

    private String esc(String val) {
        return conf.valueBracketStart + prep(val) + conf.valueBracketEnd;
    }
}