Skip to content

Commit

Permalink
Added option to define charset for shapefile export (#216)
Browse files Browse the repository at this point in the history
* improve charset handling for Layer and Ressource to Shapefile export

Signed-off-by: Nikolaos Pringouris <nprigour@gmail.com>

* Amend pull request to handle coexistence of shp.encoding system variable
and P_DEFAULT_CHARSET preference value  

Signed-off-by: Nikolaos Pringouris <nprigour@gmail.com>

* updated documentation pages related to layer export

Signed-off-by: Nikolaos Pringouris <nprigour@gmail.com>
  • Loading branch information
nprigour authored and fgdrf committed Mar 13, 2017
1 parent a9915fa commit ea45b5f
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 17 deletions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions docs/user/en/reference/Layer to Shapefile Wizard.rst
Expand Up @@ -26,6 +26,9 @@ List of selected layers:
- Projection: Shows the projection of the layer; you can change setting to transform the contents
into the requested projection. The projection information will be stored in the resulting **prj**
file.
- Charset: Shapefile charset encoding; you can control the encoding of string fields during
export. The proposed value is controlled by the startup system property **shp.encoding** or if not
specified by the preference value **General-->udig UI-->Default Character Set**

**Related concepts**

Expand Down
3 changes: 3 additions & 0 deletions docs/user/en/reference/Resource to Shapefile Wizard.rst
Expand Up @@ -29,6 +29,9 @@ List of selected resources:
- Projection: Shows the projection of the resource; you can change setting to transform the
contents into the requested projection. The projection information will be stored in the
resulting **prj** file.
- Charset: Shapefile charset encoding; you can control the encoding of string fields during
export. The proposed value is controlled by the startup system property **shp.encoding** or if not
specified by the preference value **General-->udig UI-->Default Character Set**

**Related concepts**

Expand Down
Expand Up @@ -10,6 +10,7 @@
*/
package org.locationtech.udig.catalog.internal.shp;

import java.nio.charset.Charset;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.ConsoleHandler;
Expand Down Expand Up @@ -172,8 +173,25 @@ public void setUseSpatialIndex( boolean useSpatialIndex ) {
getPreferenceStore().setValue(PreferenceConstants.P_CREATE_INDEX, useSpatialIndex);
}

/**
* The value is set according to the system parameter "shp.encoding" if not present or not valid
* then charset is obtained from UI plugin charset value
*
* @return the charset to be used as String
*/
public String defaultCharset() {
return UiPlugin.getDefault().getPreferenceStore().getString(org.locationtech.udig.ui.preferences.PreferenceConstants.P_DEFAULT_CHARSET);
String charsetName = System.getProperty(ShpServiceExtension.SHP_CHARSET_PARAM_NAME);
if (charsetName != null) {
try {
//test that Charset actually exists
return Charset.forName(charsetName).name();
} catch (Exception e) {
getDefault().getLog().log(new Status(IStatus.WARNING, ID,
"Unable to parse charset " + charsetName + ". Default UI charset will be used for shp encoding"));
}
}
return UiPlugin.getDefault().getPreferenceStore().getString(
org.locationtech.udig.ui.preferences.PreferenceConstants.P_DEFAULT_CHARSET);
}

}
Expand Up @@ -13,8 +13,8 @@

import java.io.File;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -26,7 +26,6 @@

import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFactorySpi;
import org.geotools.data.DataUtilities;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;

/**
Expand All @@ -37,6 +36,10 @@
*/
public class ShpServiceExtension extends AbstractDataStoreServiceExtension implements ServiceExtension {

//name of system variable to hold the charset encoding to be used during
//shp service creation. Should be defined as a system variable during startup
public static String SHP_CHARSET_PARAM_NAME = "shp.encoding";

// this is for backwards compatibility with 1.1.x. The parameter key was
// changed in geotools since 2.2
private static final String OLD_URLP_KEY = "shapefile url"; //$NON-NLS-1$
Expand Down Expand Up @@ -108,7 +111,14 @@ public Map<String,Serializable> createParams( URL url ) {
return null; // file does not exist?
}
HashMap<String,Serializable> params = new HashMap<String,Serializable>();
params.put(ShapefileDataStoreFactory.URLP.key,cleanedShapeURL);
params.put(ShapefileDataStoreFactory.URLP.key,cleanedShapeURL);

//set the charset to be used for the shapefile during loading
Charset charset = getCharsetParam();
if (charset != null) {
params.put(ShapefileDataStoreFactory.DBFCHARSET.key, charset.name());
}

return params;
}
return null;
Expand Down Expand Up @@ -181,4 +191,12 @@ public String reasonForFailure( URL url ) {
return reasonForFailure(createParams(url));
}

/**
* Sets the charset to be used during service creation.
*
* @param params
*/
private Charset getCharsetParam() {
return Charset.forName(ShpPlugin.getDefault().defaultCharset());
}
}
Expand Up @@ -14,6 +14,7 @@
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -40,6 +41,7 @@
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
Expand All @@ -55,6 +57,7 @@
import org.geotools.referencing.CRS;
import org.geotools.referencing.operation.transform.IdentityTransform;
import org.geotools.referencing.wkt.UnformattableObjectException;

import org.locationtech.udig.catalog.CatalogPlugin;
import org.locationtech.udig.catalog.ICatalog;
import org.locationtech.udig.catalog.IGeoResource;
Expand All @@ -71,6 +74,7 @@
import org.locationtech.udig.catalog.ui.workflow.WorkflowWizardPageProvider;
import org.locationtech.udig.ui.PlatformGIS;
import org.locationtech.udig.ui.ProgressManager;

import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
Expand Down Expand Up @@ -236,7 +240,7 @@ else if (fromCRS != null)
(Class< ? extends Geometry>) schema.getGeometryDescriptor().getType()
.getBinding(), crs);

ShapefileDataStore shapefile = createShapefile(destinationFeatureType, file);
ShapefileDataStore shapefile = createShapefile(destinationFeatureType, file, data.getCharset());
SimpleFeatureType targetFeatureType = shapefile.getSchema();

ReprojectingFeatureCollection processed = new ReprojectingFeatureCollection(fc, monitor, targetFeatureType, mt);
Expand Down Expand Up @@ -475,7 +479,7 @@ private void exportLineFeatures( Data data, IProgressMonitor currentMonitor, Fil
throws IllegalFilterException, IOException, SchemaException, MalformedURLException {

File lineFile = addFileNameSuffix(file, LINE_SUFFIX);
ShapefileDataStore shapefile = createShapefile(createFeatureType(schema, MultiLineString.class, data.getCRS()), lineFile);
ShapefileDataStore shapefile = createShapefile(createFeatureType(schema, MultiLineString.class, data.getCRS()), lineFile, data.getCharset());
SimpleFeatureType targetFeatureType = shapefile.getSchema();

SimpleFeatureCollection temp = new ToMultiLineFeatureCollection(
Expand All @@ -493,7 +497,7 @@ private void exportPointFeatures( Data data, IProgressMonitor currentMonitor, Fi
throws IllegalFilterException, IOException, SchemaException, MalformedURLException {

File pointFile = addFileNameSuffix(file, POINT_SUFFIX);
ShapefileDataStore shapefile = createShapefile(createFeatureType(schema, MultiPoint.class, data.getCRS()), pointFile);
ShapefileDataStore shapefile = createShapefile(createFeatureType(schema, MultiPoint.class, data.getCRS()), pointFile, data.getCharset());
SimpleFeatureType targetFeatureType = shapefile.getSchema();

SimpleFeatureCollection temp = new ToMultiPointFeatureCollection(
Expand All @@ -511,7 +515,7 @@ private void exportPolygonFeatures( Data data, IProgressMonitor currentMonitor,
throws IllegalFilterException, IOException, SchemaException, MalformedURLException {

File polyFile = addFileNameSuffix(file, POLY_SUFFIX);
ShapefileDataStore shapefile = createShapefile(createFeatureType(schema, MultiPolygon.class, data.getCRS()), polyFile);
ShapefileDataStore shapefile = createShapefile(createFeatureType(schema, MultiPolygon.class, data.getCRS()), polyFile, data.getCharset());
SimpleFeatureType targetFeatureType = shapefile.getSchema();

SimpleFeatureCollection temp = new ToMultiPolygonFeatureCollection(
Expand Down Expand Up @@ -617,7 +621,7 @@ private org.opengis.filter.Filter createGeometryTypeFilter( String geomName, Str



private ShapefileDataStore createShapefile( SimpleFeatureType targetType, File file) throws IOException {
private ShapefileDataStore createShapefile( SimpleFeatureType targetType, File file, Charset charset) throws IOException {

if (!canWrite(file)) {
throw new IOException(MessageFormat.format(Messages.CatalogExport_cannotWrite, file
Expand All @@ -629,6 +633,9 @@ private ShapefileDataStore createShapefile( SimpleFeatureType targetType, File f
params.put("url", URLUtils.fileToURL(file)); //$NON-NLS-1$
params.put("create spatial index", Boolean.TRUE); //$NON-NLS-1$
ShapefileDataStore ds = (ShapefileDataStore) dataStoreFactory.createDataStore(params);
if (charset != null) {
ds.setCharset(charset);
}
ds.createSchema(targetType);


Expand Down
Expand Up @@ -11,12 +11,15 @@
package org.locationtech.udig.catalog.ui.export;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.HashSet;

import org.geotools.data.Query;

import org.locationtech.udig.catalog.IGeoResource;
import org.locationtech.udig.ui.ProgressManager;

import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
Expand All @@ -32,6 +35,7 @@ public class Data {
private Query query;
private String name;
private boolean checked;
private Charset charset;

public String getName() {
return name;
Expand Down Expand Up @@ -103,6 +107,12 @@ public void setChecked( boolean checked ) {
this.checked = checked;
}


public Charset getCharset() {
return charset;
}

public void setCharset(Charset charset) {
this.charset = charset;
}

}
Expand Up @@ -10,6 +10,7 @@
package org.locationtech.udig.catalog.ui.export;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -19,6 +20,7 @@
import org.locationtech.udig.catalog.ui.workflow.WorkflowWizard;
import org.locationtech.udig.catalog.ui.workflow.WorkflowWizardPage;
import org.locationtech.udig.ui.CRSDialogCellEditor;
import org.locationtech.udig.ui.CharsetDialogCellEditor;

import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IPageChangedListener;
Expand Down Expand Up @@ -56,6 +58,7 @@
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;

import org.geotools.data.FeatureSource;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

Expand Down Expand Up @@ -114,8 +117,9 @@ public void selectionChanged( SelectionChangedEvent event ) {
viewer.setAutoExpandLevel(3);

final String crs="CRS"; //$NON-NLS-1$
viewer.setColumnProperties(new String[]{"name",crs}); //$NON-NLS-1$
viewer.setCellEditors(new CellEditor[]{new TextCellEditor(tree), new CRSDialogCellEditor(tree)});
final String charset="charset"; //$NON-NLS-1$
viewer.setColumnProperties(new String[]{"name",crs, charset}); //$NON-NLS-1$
viewer.setCellEditors(new CellEditor[]{new TextCellEditor(tree), new CRSDialogCellEditor(tree), new CharsetDialogCellEditor(tree)});
viewer.setCellModifier(new ICellModifier(){

public boolean canModify( Object element, String property ) {
Expand All @@ -126,6 +130,8 @@ public Object getValue( Object element, String property ) {
Data data = (Data)element;
if( crs.equals(property) ){
return data.getCRS();
} else if (charset.equals(property)) {
return data.getCharset();
}else{
if( data.getName()==null ){
return ((ExportResourceLabelProvider)viewer.getLabelProvider()).getColumnText(data, 0);
Expand All @@ -140,7 +146,9 @@ public void modify( Object element, String property, Object value ) {
TreeItem item=(TreeItem) element;
Data data=(Data) item.getData();
if( crs.equals(property) ){
data.setCRS((CoordinateReferenceSystem)value);
data.setCRS((CoordinateReferenceSystem)value);
} else if (charset.equals(property)) {
data.setCharset((Charset) value);
}else{
data.setName((String) value);
}
Expand Down Expand Up @@ -256,6 +264,7 @@ private Tree createTree( Tree tree ) {
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnWeightData(1,true));
tableLayout.addColumnData(new ColumnWeightData(1,true));
tableLayout.addColumnData(new ColumnWeightData(1,true));
tree.setLayout(tableLayout);

TreeColumn name=new TreeColumn(tree, SWT.DEFAULT);
Expand All @@ -266,6 +275,10 @@ private Tree createTree( Tree tree ) {
projection.setMoveable(false);
projection.setResizable(true);

TreeColumn charset =new TreeColumn(tree, SWT.DEFAULT);
charset.setMoveable(false);
charset.setResizable(true);

return tree;
}

Expand Down Expand Up @@ -420,7 +433,8 @@ public Image getColumnImage( Object element, int columnIndex ) {
return wrapped.getImage(data.getResource());
case 1:
return null;

case 2:
return null;
default:
break;
}
Expand All @@ -441,9 +455,18 @@ public String getColumnText( Object element, int columnIndex ) {
return data.getName();
}
case 1:
if( crs==null )
return "undefined";
return crs.getName().toString();
if( crs==null ) {
return "undefined"; //$NON-NLS-1$
} else {
return crs.getName().toString();
}
case 2:
if( data.getCharset()==null ) {
//addition to handle problem with charset always being set to ISO-8859-1
data.setCharset((System.getProperty("shp.encoding") != null) ?
Charset.forName(System.getProperty("shp.encoding")) : Charset.defaultCharset());
}
return data.getCharset().displayName();

default:
break;
Expand Down
Expand Up @@ -149,6 +149,9 @@ public List<IService> createService( final URL targetUrl ) {
Map<String, Serializable> connectionParameters = candidateEntry.getValue();
try {
IService sevice = serviceExtension.createService(null, connectionParameters);
if (sevice == null) {
continue;
}
CatalogImpl.runInterceptor(sevice, ServiceInterceptor.CREATED_ID);
candidates.add(sevice);
// List<IService> service = createService(connectionParameters);
Expand Down

0 comments on commit ea45b5f

Please sign in to comment.