/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/exse/ lat/lon Fitzke/Fretter/Poth GbR http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon Fitzke/Fretter/Poth GbR Meckenheimer Allee 176 53115 Bonn Germany E-Mail: poth@lat-lon.de Jens Fitzke Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: jens.fitzke@uni-bonn.de ---------------------------------------------------------------------------*/ package de.latlon.deejump.plugin.style; import static com.vividsolutions.jump.workbench.ui.MenuNames.LAYER; import static com.vividsolutions.jump.workbench.ui.MenuNames.STYLE; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.HashMap; import java.util.Map; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JFileChooser; import javax.swing.JPopupMenu; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.openjump.core.ui.images.IconLoader; import org.openjump.core.ui.util.ScreenScale; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jump.I18N; import com.vividsolutions.jump.feature.AttributeType; import com.vividsolutions.jump.feature.BasicFeature; import com.vividsolutions.jump.feature.FeatureSchema; import com.vividsolutions.jump.util.Blackboard; import com.vividsolutions.jump.util.java2xml.Java2XML; import com.vividsolutions.jump.workbench.WorkbenchContext; import com.vividsolutions.jump.workbench.model.Layer; import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn; import com.vividsolutions.jump.workbench.plugin.EnableCheck; import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory; import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck; import com.vividsolutions.jump.workbench.plugin.PlugInContext; import com.vividsolutions.jump.workbench.ui.GUIUtil; import com.vividsolutions.jump.workbench.ui.LayerViewPanel; import com.vividsolutions.jump.workbench.ui.MultiInputDialog; import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller; import com.vividsolutions.jump.workbench.ui.plugin.PersistentBlackboardPlugIn; /** * ... * * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei </a> * */ public class LayerStyle2SLDPlugIn extends AbstractPlugIn { private static final Logger LOG = Logger.getLogger(LayerStyle2SLDPlugIn.class); public static final ImageIcon ICON = IconLoader.icon("sld_out_16.png"); /** * The <code>Transformer</code> object used in the transformation of a * task/project/layer xml to sld. */ protected static Transformer transformer = null; private static final String UTF_8 = "UTF-8"; static { initTransformer(); } private Java2XML java2Xml = new Java2XML(); private JFileChooser fileChooser; private MultiInputDialog dialog; private String styleTitle, geomProperty, styleName, wmsLayerName, namespace; //private String prefix; private String featureTypeStyle; private double scaleFactor = 1d; @Override public String getName() { return I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Transform-layer-style-into-sld"); } /** * Use this method to install the LayerStyle2SLD plugin in the toolbar * * @param context * @throws Exception */ public void install(PlugInContext context) throws Exception { context.getWorkbenchContext().getWorkbench().getFrame().getToolBar() .addPlugIn(getIcon(), this, createEnableCheck(context.getWorkbenchContext()), context.getWorkbenchContext()); } @Override public void initialize(PlugInContext context) throws Exception { FeatureInstaller featureInstaller = new FeatureInstaller(context.getWorkbenchContext()); EnableCheck enableCheck = createEnableCheck(context.getWorkbenchContext()); JPopupMenu popupMenu = context.getWorkbenchFrame().getLayerNamePopupMenu(); featureInstaller.addPopupMenuItem(popupMenu, this, new String[]{STYLE}, this.getName(), false, ICON, enableCheck); featureInstaller.addMainMenuItem(this, new String[] {LAYER}, this.getName(), // name methode .getName() (see AbstractPlugIn) false, ICON, enableCheck); } @Override public boolean execute(PlugInContext context) throws Exception { Blackboard bb = PersistentBlackboardPlugIn.get(context.getWorkbenchContext()); String fileName = (String) bb.get("LayerStyle2SLDPlugIn.filename"); reportNothingToUndoYet(context); Layer layer = context.getSelectedLayer(0); if (layer == null) { return false; } geomProperty = "GEOM"; FeatureSchema schema = layer.getFeatureCollectionWrapper().getFeatureSchema(); for (int i = 0; i < schema.getAttributeCount(); ++i) { if (schema.getAttributeType(i) == AttributeType.GEOMETRY) { geomProperty = schema.getAttributeName(i); } } initDialog(context); dialog.setVisible(true); if (!dialog.wasOKPressed()) { return false; } // why the field name given when constructing the dialog are used both // for the label and // for the key is beyond me wmsLayerName = dialog.getText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.WMS-Layer-name")); styleName = dialog.getText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Style-name")); styleTitle = dialog.getText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Style-title")); featureTypeStyle = dialog.getText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Feature-Type-Style")); geomProperty = dialog.getText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.geomProperty")); namespace = dialog.getText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Namespace")); //prefix = namespace.substring(namespace.lastIndexOf('/') + 1); if (fileChooser == null) { fileChooser = new JFileChooser(); if (fileName != null) { fileChooser.setCurrentDirectory(new File(fileName).getParentFile()); } fileChooser.setApproveButtonText(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Save")); fileChooser.setDialogTitle(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Save-style-as-SLD")); } if (JFileChooser.APPROVE_OPTION == fileChooser.showOpenDialog(context .getWorkbenchFrame())) { File file = File.createTempFile("temptask", ".xml"); file.deleteOnExit(); bb.put("LayerStyle2SLDPlugIn.filename", fileChooser .getSelectedFile().getAbsoluteFile().toString()); scaleFactor = calcScaleFactor(context.getLayerViewPanel()); transformXML(layer, file, fileChooser.getSelectedFile(), scaleFactor); } return true; } private void initDialog(PlugInContext context) { if (dialog == null) { dialog = new MultiInputDialog( context.getWorkbenchFrame(), I18N.get("deejump.pluging.style.LayerStyle2SLDPlugIn.SLD-Parameters"), true); dialog.addSeparator(); dialog.addTextField(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.geomProperty"), geomProperty, 25, null, I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Input-the-name-of-the-geometry-property")); dialog.addSeparator(); String name = context.getCandidateLayer(0).getName(); dialog.addTextField(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.WMS-Layer-name"), name, 25, null, I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.WMS-Layer-name")); dialog.addTextField(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Style-name"), name, 25, null, I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Style-name")); dialog.addTextField(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Style-title"), name, 25, null, I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Style-title")); dialog.addTextField(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Feature-Type-Style"), name, 25, null, I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Feature-Type-Style")); dialog.addTextField(I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Namespace"), "http://www.deegree.org/app", 25, null, I18N .get("deejump.pluging.style.LayerStyle2SLDPlugIn.Namespace")); GUIUtil.centreOnWindow(dialog); } } private void transformXML(Layer layer, File inputXML, File outputXML, double scaleFactor) throws Exception { // TODO don't assume has 1 item!!! // Should create this condition in EnableCheckFactory if (layer.getFeatureCollectionWrapper().getFeatures().size() == 0) { throw new Exception(I18N.get("org.openjump.core.ui.plugin.tools.statistics.StatisticOverViewPlugIn.Selected-layer-is-empty")); } BasicFeature bf = (BasicFeature) layer.getFeatureCollectionWrapper() .getFeatures().get(0); Geometry geo = bf.getGeometry(); String geoType = geo.getGeometryType(); java2Xml.write(layer, "layer", inputXML); FileInputStream input = new FileInputStream(inputXML); // FileWriter fw = new FileWriter( outputXML ); OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream( outputXML), UTF_8); HashMap<String, String> map = new HashMap<String, String>(9); map.put("wmsLayerName", wmsLayerName); map.put("featureTypeStyle", featureTypeStyle); map.put("styleName", styleName); map.put("styleTitle", styleTitle); map.put("geoType", geoType); map.put("geomProperty", geomProperty); map.put("Namespace", namespace); //map.put("NamespacePrefix", prefix + ":"); //map.put("NamespacePrefixWithoutColon", prefix); // ATENTION : note that min and max are swapped in JUMP!!! // will swap later, in transformContext Double d = layer.getMinScale(); d = d != null ? d : new Double(0); map.put("minScale", "" + toRealWorldScale(scaleFactor, d.doubleValue())); // using Double.MAX_VALUE is creating a large number - too many 0's // make it simple and hardcde a large number final double largeNumber = 99999999999d; d = layer.getMaxScale(); d = d != null ? d : new Double(largeNumber); map.put("maxScale", "" + toRealWorldScale(scaleFactor, d.doubleValue())); fw.write(transformContext(input, map)); fw.close(); } /** * @return the icon */ public Icon getIcon() { return new ImageIcon(LayerStyle2SLDPlugIn.class.getResource("sldstyle.png")); } /** * @param layerXML * @param parMap * @return the transformed XML (?) * @throws TransformerException * @throws UnsupportedEncodingException */ public static String transformContext(InputStream layerXML, Map<String, String> parMap) throws TransformerException, UnsupportedEncodingException { return transformContext(new InputStreamReader(layerXML, UTF_8), parMap); } /** * @param layerXML * @param parMap * @return the transformed XML (?) * @throws TransformerException */ public static String transformContext(Reader layerXML, Map<String, String> parMap) throws TransformerException { StringWriter sw = new StringWriter(); StreamResult sr = new StreamResult(sw); StreamSource streamSource = new StreamSource(layerXML); // if you don't clear the pars, xalan throws a nasty NPE transformer.clearParameters(); for (String key : parMap.keySet()) { transformer.setParameter(key, parMap.get(key)); } transformer.transform(streamSource, sr); try { sw.close(); } catch (IOException e) { e.printStackTrace(); } if (LOG.getLevel() == Level.DEBUG) { LOG.debug(sw.toString()); } return sw.toString(); } private static void initTransformer() { try { URL xslUrl = LayerStyle2SLDPlugIn.class.getResource("layerstyle2sld.xsl"); TransformerFactory transformerFactory = TransformerFactory.newInstance(); InputStreamReader isr = new InputStreamReader(xslUrl.openStream(), UTF_8); StreamSource streamSrc = new StreamSource(isr); transformer = transformerFactory.newTransformer(streamSrc); } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerFactoryConfigurationError e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * @param workbenchContext * @return the enable check */ public EnableCheck createEnableCheck(final WorkbenchContext workbenchContext) { EnableCheckFactory ecf = new EnableCheckFactory(workbenchContext); MultiEnableCheck mec = new MultiEnableCheck() .add(ecf.createWindowWithLayerNamePanelMustBeActiveCheck()) .add(ecf.createExactlyNLayerablesMustBeSelectedCheck(1, Layer.class)); return mec; } /** * @param scaleFactor * @param jumpScale * @return the scale */ public static final Double toRealWorldScale(double scaleFactor, double jumpScale) { return new Double(jumpScale / scaleFactor); } private double calcScaleFactor(LayerViewPanel panel) { double internalScale = 1d / panel.getViewport().getScale(); double realScale = ScreenScale.getHorizontalMapScale(panel.getViewport()); return internalScale / realScale; } }