Package org.geoserver.wfs.response

Source Code of org.geoserver.wfs.response.CSVOutputFormat

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wfs.response;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.regex.Pattern;

import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.impl.XSDElementDeclarationImpl;
import org.geoserver.config.GeoServer;
import org.geoserver.platform.Operation;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.WFSGetFeatureOutputFormat;
import org.geoserver.wfs.request.FeatureCollectionResponse;
import org.geoserver.wfs.request.GetFeatureRequest;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.type.DateUtil;
import org.opengis.feature.Feature;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.PropertyDescriptor;

/**
* WFS output format for a GetFeature operation in which the outputFormat is "csv".
* The refence specification for this format can be found in this RFC:
* http://www.rfc-editor.org/rfc/rfc4180.txt
*
* @author Justin Deoliveira, OpenGeo, jdeolive@opengeo.org
* @author Sebastian Benthall, OpenGeo, seb@opengeo.org
* @author Andrea Aime, OpenGeo
*/
public class CSVOutputFormat extends WFSGetFeatureOutputFormat {

    static final Pattern CSV_ESCAPES = Pattern.compile("[\"\n,\r]");

    public CSVOutputFormat(GeoServer gs) {
        //this is the name of your output format, it is the string
        // that will be used when requesting the format in a
        // GEtFeature request:
        // ie ;.../geoserver/wfs?request=getfeature&outputFormat=myOutputFormat
        super(gs, "csv");
    }
   
    /**
     * @return "text/csv";
     */
    @Override
    public String getMimeType(Object value, Operation operation)
               throws ServiceException {
        // won't allow browsers to open it directly, but that's the mime
        // state in the RFC
        return "text/csv";
    }

    @Override
    public String getPreferredDisposition(Object value, Operation operation) {
        return DISPOSITION_ATTACH;
    }
   
    @Override
    public String getAttachmentFileName(Object value, Operation operation) {
        GetFeatureRequest request = GetFeatureRequest.adapt(operation.getParameters()[0]);
        String outputFileName = request.getQueries().get(0).getTypeNames().get(0).getLocalPart();
        return outputFileName + ".csv";
    }
   
    /**
     * @see WFSGetFeatureOutputFormat#write(Object, OutputStream, Operation)
     */
    @Override
    protected void write(FeatureCollectionResponse featureCollection,
            OutputStream output, Operation getFeature) throws IOException,
            ServiceException {
         //write out content here
       
        //create a writer
        BufferedWriter w = new BufferedWriter( new OutputStreamWriter( output, gs.getGlobal().getSettings().getCharset() ) );
                  
        //get the feature collection
        FeatureCollection<?, ?> fc =
            featureCollection.getFeature().get(0);          
       
        if (fc.getSchema() instanceof SimpleFeatureType) {
            //write out the header
            SimpleFeatureType ft = (SimpleFeatureType) fc.getSchema();
            w.write("FID,");
            for ( int i = 0; i < ft.getAttributeCount(); i++ ) {
                AttributeDescriptor ad = ft.getDescriptor( i );
                w.write( prepCSVField(ad.getLocalName()) );
                  
                if ( i < ft.getAttributeCount()-1 ) {
                   w.write( "," );
                }
            }
        } else {
            // complex features
            w.write("gml:id,");

            int i = 0;
            for (PropertyDescriptor att : fc.getSchema().getDescriptors()) {
                // exclude temporary attributes
                if (!att.getName().getLocalPart().startsWith("FEATURE_LINK")) {
                    if (i > 0) {
                        w.write(",");
                    }
                    String elName = att.getName().toString();
                    Object xsd = att.getUserData().get(XSDElementDeclaration.class);
                    if (xsd != null && xsd instanceof XSDElementDeclarationImpl) {
                        // get the prefixed name if possible
                        // otherwise defaults to the full name with namespace URI
                        XSDElementDeclarationImpl xsdEl = (XSDElementDeclarationImpl) xsd;
                        elName = xsdEl.getQName();
                    }
                    w.write(prepCSVField(elName));
                    i++;
                }
            }
        }
        // by RFC each line is terminated by CRLF
        w.write( "\r\n" );
       
        // prepare the formatter for numbers
        NumberFormat coordFormatter = NumberFormat.getInstance(Locale.US);
        coordFormatter.setMaximumFractionDigits(getInfo().getGeoServer().getSettings().getNumDecimals());
        coordFormatter.setGroupingUsed(false);
          
        //write out the features
        FeatureIterator<?> i = fc.features();
        try {
            while( i.hasNext() ) {               
                Feature f = i.next();
                // dump fid
                w.write(prepCSVField(f.getIdentifier().getID()));
                w.write(",");
                if (f instanceof SimpleFeature) {
                    // dump attributes
                    for ( int j = 0; j < ((SimpleFeature) f).getAttributeCount(); j++ ) {
                        Object att = ((SimpleFeature) f).getAttribute( j );
                        if ( att != null ) {
                            String value = formatToString(att, coordFormatter);
                            w.write( prepCSVField(value) );
                        }
                        if ( j < ((SimpleFeature) f).getAttributeCount()-1 ) {
                            w.write(",");   
                        }
                    }
                } else {
                    // complex feature
                    Iterator<PropertyDescriptor> descriptors = fc.getSchema().getDescriptors().iterator();
                   
                    // dump attributes
                    int j = 0;
                    while (descriptors.hasNext()) {
                        PropertyDescriptor desc = descriptors.next();
                       
                        if (desc.getName().getLocalPart().startsWith("FEATURE_LINK")) {
                            // skip temporary attributes
                            continue;
                        }
                        if (j > 0) {
                            w.write(",");
                        }
                        j++;
                        // Multi valued properties aren't supported, only for SF0 for now
                        Collection<Property> values = f.getProperties(desc.getName());
                        if (values.size() > 1) {
                            throw new UnsupportedOperationException(
                                    "Multi valued properties aren't supported with CSV format!");
                        }

                        Object att = null;
                        if (!values.isEmpty()) {
                            att = values.iterator().next().getValue();
                        }

                        if (att != null) {
                            String value = formatToString(att, coordFormatter);
                            w.write(prepCSVField(value));
                        }    
                    }
                }
                // by RFC each line is terminated by CRLF
                w.write("\r\n");
            }
        } finally {
            i.close();
        }
          
        w.flush();
    }
   
    private String formatToString(Object att, NumberFormat coordFormatter) {
        String value = null;
        if (att instanceof Number) {
            // don't allow scientific notation in the output, as OpenOffice won't
            // recognize that as a number
            value = coordFormatter.format(att);
        } else if (att instanceof Date) {
            // serialize dates in ISO format
            if (att instanceof java.sql.Date)
                value = DateUtil.serializeSqlDate((java.sql.Date) att);
            else if (att instanceof java.sql.Time)
                value = DateUtil.serializeSqlTime((java.sql.Time) att);
            else
                value = DateUtil.serializeDateTime((Date) att);
        } else {
            // everything else we just "toString"
            value = att.toString();
        }
        return value;
    }

    /*
     * The CSV "spec" explains that fields with certain properties must be
     * delimited by double quotes, and also that double quotes within fields
     * must be escaped.  This method takes a field and returns one that
     * obeys the CSV spec.
     */   
    private String prepCSVField(String field){
      // "embedded double-quote characters must be represented by a pair of double-quote characters."
      String mod = field.replaceAll("\"", "\"\"");
     
      /*
       * Enclose string in double quotes if it contains double quotes, commas, or newlines
       */
        if (CSV_ESCAPES.matcher(mod).find()) {
            mod = "\"" + mod + "\"";
      }
     
    return mod;
     
    }
   
    @Override
    public String getCapabilitiesElementName() {
      return "CSV";
    }
   
    @Override
    public String getCharset(Operation operation){
        return gs.getGlobal().getSettings().getCharset();
    }

}
TOP

Related Classes of org.geoserver.wfs.response.CSVOutputFormat

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.