rrenkert@41: package de.intevation.mxd.writer;
rrenkert@41:
rrenkert@41: import org.apache.log4j.Logger;
rrenkert@41:
rrenkert@41: import org.w3c.dom.Document;
rrenkert@41: import org.w3c.dom.Element;
rrenkert@41: import org.w3c.dom.NodeList;
rrenkert@42:
rrenkert@98: import java.io.File;
rrenkert@98:
rrenkert@41: import javax.xml.xpath.XPathConstants;
rrenkert@41:
rrenkert@41: import edu.umn.gis.mapscript.mapObj;
rrenkert@41: import edu.umn.gis.mapscript.layerObj;
rrenkert@42: import edu.umn.gis.mapscript.classObj;
rrenkert@42:
rrenkert@41: import edu.umn.gis.mapscript.MS_UNITS;
rrenkert@42: import edu.umn.gis.mapscript.MS_LAYER_TYPE;
vc11884admin@130: import edu.umn.gis.mapscript.MS_CONNECTION_TYPE;
rrenkert@41:
rrenkert@41: import de.intevation.mxd.utils.XMLUtils;
rrenkert@41:
rrenkert@41: /**
rrenkert@43: * The Mapfile Writer.
rrenkert@43: * This Writer uses the MapScript Java API to create Mapfiles from a DOM.
rrenkert@41: *
rrenkert@41: * @author Raimund Renkert
rrenkert@41: */
rrenkert@41: public class MapScriptWriter
rrenkert@41: implements IWriter
rrenkert@41: {
rrenkert@43: /**
rrenkert@43: * The Logger.
rrenkert@43: */
rrenkert@43: private static final Logger logger = Logger.getLogger(MapScriptWriter.class);
rrenkert@43:
rrenkert@43: /**
rrenkert@43: * Private member.
rrenkert@43: */
rrenkert@41: private Document root;
rrenkert@41: private mapObj map;
rrenkert@55: private String mapFilename;
vc11884admin@130: private String MS_BINDIR = "c:/ms_6.1-dev/bin";
vc11884admin@134: private String prefix = "";
vc11884admin@170: private MS_UNITS units = MS_UNITS.MS_METERS;
rrenkert@41:
rrenkert@41: public MapScriptWriter() {
rrenkert@55: map = new mapObj("");
rrenkert@55: mapFilename = "";
rrenkert@41: }
rrenkert@41:
rrenkert@55: public MapScriptWriter(String templ, String filename) {
rrenkert@55: map = new mapObj(templ);
rrenkert@55: mapFilename = filename;
rrenkert@41: }
rrenkert@41:
rrenkert@43: /**
rrenkert@43: * Write the mapfile.
rrenkert@43: * @param doc The root document containin the map attributes.
rrenkert@43: *
rrenkert@43: * @return Currently always true.
rrenkert@43: */
rrenkert@120: public boolean write(Document doc) {
rrenkert@41: logger.debug("write()");
rrenkert@41: this.root = doc;
rrenkert@41:
rrenkert@41: //Get the filename.
rrenkert@41: Element fileNode = (Element)XMLUtils.xpath(
rrenkert@41: root,
rrenkert@41: "/mxd/file",
rrenkert@41: XPathConstants.NODE);
rrenkert@41: //Write the map attributes.
rrenkert@41: writeMap();
rrenkert@42: //Write the layers.
rrenkert@42: writeLayer();
rrenkert@41: //Save the map.
rrenkert@42: mapObj cloneMap = map.cloneMap();
rrenkert@55: cloneMap.save(mapFilename);
rrenkert@120: logger.info("Mapfile successfully created.");
rrenkert@41: return true;
rrenkert@41: }
rrenkert@41:
rrenkert@43: /**
rrenkert@43: * Create the map object and set the attributes.
rrenkert@43: */
rrenkert@41: private void writeMap() {
rrenkert@41: logger.debug("writeMap()");
rrenkert@41: //Get the map.
rrenkert@41: Element mapNode = (Element)XMLUtils.xpath(
rrenkert@41: root,
rrenkert@41: "/mxd/map",
rrenkert@41: XPathConstants.NODE);
rrenkert@41:
rrenkert@41: //Set the name.
rrenkert@41: map.setName(mapNode.getAttribute("name"));
rrenkert@42: map.setMetaData("wms_title", mapNode.getAttribute("name"));
rrenkert@41: //Set the extent.
rrenkert@41: map.setExtent(
rrenkert@41: Double.parseDouble(mapNode.getAttribute("extent_min_x")),
rrenkert@41: Double.parseDouble(mapNode.getAttribute("extent_min_y")),
rrenkert@41: Double.parseDouble(mapNode.getAttribute("extent_max_x")),
rrenkert@41: Double.parseDouble(mapNode.getAttribute("extent_max_y")));
rrenkert@41:
vc11884admin@172: //Set the units and projection.
vc11884admin@172: int proj = Integer.parseInt(mapNode.getAttribute("projection"));
vc11884admin@172: if(proj != 0) {
vc11884admin@172: map.setProjection("epsg:" + mapNode.getAttribute("projection"));
vc11884admin@172: }
vc11884admin@170: String u = mapNode.getAttribute("units");
vc11884admin@170: if(u.equals("feet")) {
vc11884admin@170: units = MS_UNITS.MS_FEET;
rrenkert@41: }
vc11884admin@170: else if(u.equals("inches")) {
vc11884admin@170: units = MS_UNITS.MS_INCHES;
rrenkert@41: }
vc11884admin@170: else if(u.equals("kilometers")) {
vc11884admin@170: units = MS_UNITS.MS_KILOMETERS;
rrenkert@41: }
vc11884admin@170: else if(u.equals("meters")) {
vc11884admin@170: units = MS_UNITS.MS_METERS;
rrenkert@41: }
vc11884admin@170: else if(u.equals("miles")) {
vc11884admin@170: units = MS_UNITS.MS_MILES;
vc11884admin@170: }
vc11884admin@170: else if(u.equals("nauticalmiles")) {
vc11884admin@170: units = MS_UNITS.MS_NAUTICALMILES;
vc11884admin@170: }
vc11884admin@170: else if(u.equals("points")) {
vc11884admin@170: units = MS_UNITS.MS_PIXELS;
vc11884admin@170: }
vc11884admin@170: else if(u.equals("degree")) {
vc11884admin@170: units = MS_UNITS.MS_DD;
vc11884admin@170: }
rrenkert@41: else {
vc11884admin@170: units = MS_UNITS.MS_METERS;
rrenkert@41: }
vc11884admin@170: map.setUnits(units);
rrenkert@41:
rrenkert@41: //TODO: Find out whats the correct scale value.
rrenkert@41: //map.setScaledenom(Double.parseDouble(mapNode.getAttribute("scale")));
rrenkert@41: }
rrenkert@41:
rrenkert@43: /**
rrenkert@43: * Create layer objects and set the attributes.
rrenkert@43: */
rrenkert@120: private void writeLayer() {
rrenkert@42: logger.debug("writeLayer()");
rrenkert@42: Element mapNode = (Element)XMLUtils.xpath(
rrenkert@42: root,
rrenkert@42: "/mxd/map",
rrenkert@42: XPathConstants.NODE);
rrenkert@42: NodeList list = mapNode.getElementsByTagName("layer");
rrenkert@42: for(int i = 0; i < list.getLength(); i++) {
rrenkert@42: Element layerElement = (Element)list.item(i);
rrenkert@42: layerObj layer = new layerObj(map);
rrenkert@42:
rrenkert@42: //The layer name.
rrenkert@137: String lname = layerElement.getAttribute("name");
rrenkert@137: lname = lname.replaceAll(" ", "");
vc11884admin@132: layer.setName(lname);
vc11884admin@170: layer.setUnits(units.swigValue());
rrenkert@128: layer.setMetaData("wms_title", layerElement.getAttribute("name"));
vc11884admin@148: if(layerElement.hasAttribute("group")) {
vc11884admin@148: layer.setGroup(layerElement.getAttribute("group"));
vc11884admin@148: }
rrenkert@42: //The layer status.
rrenkert@42: String stat = layerElement.getAttribute("status");
rrenkert@42: if (stat.equals("on")) {
rrenkert@42: layer.setStatus(1);
rrenkert@42: }
rrenkert@42: else {
rrenkert@42: layer.setStatus(0);
rrenkert@42: }
rrenkert@42:
rrenkert@42: //The scale.
rrenkert@145: double maxScale = 0;
rrenkert@145: double minScale = 0;
rrenkert@145: try {
rrenkert@145: maxScale =
vc11884admin@153: Double.parseDouble(layerElement.getAttribute("min_scale"));
vc11884admin@153: minScale =
rrenkert@145: Double.parseDouble(layerElement.getAttribute("max_scale"));
rrenkert@145: }
rrenkert@145: catch(NumberFormatException nfe) {
rrenkert@145: logger.warn("Error setting scale.");
rrenkert@145: maxScale = 0;
rrenkert@145: minScale = 0;
rrenkert@145: }
rrenkert@42: layer.setMaxscaledenom(maxScale);
rrenkert@42: layer.setMinscaledenom(minScale);
rrenkert@42:
rrenkert@42: //The layer type.
rrenkert@42: String type = layerElement.getAttribute("type");
rrenkert@42: if(type.equals("point")) {
rrenkert@42: layer.setType(MS_LAYER_TYPE.MS_LAYER_POINT);
rrenkert@42: }
rrenkert@62: else if (type.equals("line")) {
rrenkert@62: layer.setType(MS_LAYER_TYPE.MS_LAYER_LINE);
rrenkert@62: }
rrenkert@97: else if (type.equals("polygon")) {
rrenkert@97: layer.setType(MS_LAYER_TYPE.MS_LAYER_POLYGON);
rrenkert@97: }
rrenkert@102: layer.setTileitem("");
rrenkert@42:
rrenkert@42: //The layer datasource.
rrenkert@137: String con_type = layerElement.getAttribute("connection_type");
vc11884admin@134: if(con_type.equals("local")) {
vc11884admin@130: String datasource = "";
vc11884admin@130: if(layerElement.hasAttribute("workspace")) {
vc11884admin@130: datasource = layerElement.getAttribute("workspace");
vc11884admin@130: datasource += File.separator;
vc11884admin@130: }
vc11884admin@130: datasource += layerElement.getAttribute("data_source");
vc11884admin@130: layer.setData(datasource);
rrenkert@137: }
rrenkert@137: else if(con_type.equals("SDE")) {
rrenkert@137: logger.info(
rrenkert@137: "SDE datasource found." +
rrenkert@137: " Please edit password in mapfile.");
rrenkert@137: layer.setConnectionType(
rrenkert@137: MS_CONNECTION_TYPE.MS_PLUGIN.swigValue(),
rrenkert@137: MS_BINDIR + "/ms/plugins/msplugin_sde_93.dll");
vc11884admin@130: layer.setConnection(
rrenkert@137: layerElement.getAttribute("server") + "," +
rrenkert@137: "port:" + layerElement.getAttribute("instance") + "," +
rrenkert@137: layerElement.getAttribute("database") + "," +
rrenkert@137: layerElement.getAttribute("user") + ",");
rrenkert@137: layer.setData(
rrenkert@137: layerElement.getAttribute("data_source") +
rrenkert@137: ",SHAPE," +
rrenkert@137: layerElement.getAttribute("version"));
rrenkert@137: layer.setProcessing("CLOSE_CONNECTION=defer");
vc11884admin@134: layer.setProcessing("ATTRIBUTE_QUALIFIED=TRUE");
rrenkert@137: if(layerElement.hasAttribute("join_table")) {
vc11884admin@134: layer.setProcessing(
rrenkert@137: "JOINTABLE=" +
rrenkert@137: layerElement.getAttribute("join_table"));
vc11884admin@134: layer.setFilter(
vc11884admin@134: "where " +
vc11884admin@134: layerElement.getAttribute("definition_query") +
vc11884admin@134: " AND " +
vc11884admin@134: layerElement.getAttribute("join_table_target") + "." +
vc11884admin@134: layerElement.getAttribute("join_field_target") + "=" +
vc11884admin@134: layerElement.getAttribute("join_table") + "." +
vc11884admin@134: layerElement.getAttribute("join_field"));
rrenkert@137: }
rrenkert@137: else {
rrenkert@137: prefix = layerElement.getAttribute("data_source");
vc11884admin@169: if(layerElement.hasAttribute("definition_query") &&
vc11884admin@169: !layerElement.getAttribute("definition_query").equals("")) {
vc11884admin@169: layer.setFilter("where " +
vc11884admin@169: layerElement.getAttribute("definition_query"));
vc11884admin@169: }
rrenkert@137: }
vc11884admin@169:
rrenkert@137: }
rrenkert@129: layer.setTemplate("PleaseInsertAValidTemplateForGFI");
rrenkert@42: //Write classes.
rrenkert@42: writeClass(layer, layerElement);
rrenkert@42: }
rrenkert@41:
rrenkert@41: }
rrenkert@41:
rrenkert@42: /**
rrenkert@42: * Adds the classes to the layer.
rrenkert@42: * @param layer Mapscript layer object.
rrenkert@42: * @param layerElement Dom element containing the class attributes.
rrenkert@42: */
rrenkert@120: private void writeClass(layerObj layer, Element layerElement) {
rrenkert@87: logger.debug("writeClass(layerObj, Element)");
rrenkert@42: //Get all renderer elements (renderer in arcgis equals class in the
rrenkert@42: //mapfile.)
rrenkert@42: NodeList list = layerElement.getElementsByTagName("renderer");
rrenkert@41:
rrenkert@42: //Create all found class objects and write the symbols and styles for
rrenkert@42: //each class.
rrenkert@42: for(int i = 0; i < list.getLength(); i++) {
rrenkert@42: Element classElement = (Element)list.item(i);
rrenkert@42: classObj co = new classObj(layer);
rrenkert@124: String name = classElement.getAttribute("label");
rrenkert@99: if (name.equals("")) {
rrenkert@99: name = layerElement.getAttribute("name");
rrenkert@99: if (list.getLength() > 1) {
rrenkert@99: name += "-" + i;
rrenkert@99: }
rrenkert@99: }
rrenkert@99: co.setName (name);
rrenkert@44: if(classElement.hasAttribute("field_count")) {
vc11884admin@152: co.setExpression(createExpression(classElement, i));
rrenkert@44: }
rrenkert@42: //Write symbols and styles.
rrenkert@97: NodeList l = classElement.getChildNodes();
vc11884admin@141: for (int j = l.getLength() - 1; j >= 0; j--) {
rrenkert@97: Element elem = (Element)l.item(j);
rrenkert@97:
rrenkert@97: String type = layerElement.getAttribute("type");
rrenkert@97: if(type.equals("point") && elem.getTagName().equals("symbol")) {
rrenkert@87: MarkerStyleWriter swriter = new MarkerStyleWriter (this.map, co);
rrenkert@97: swriter.write (elem);
rrenkert@87: }
rrenkert@97: else if(type.equals("line") && elem.getTagName().equals("symbol")) {
rrenkert@95: LineStyleWriter swriter = new LineStyleWriter (this.map, co);
rrenkert@97: swriter.write (elem);
rrenkert@97: }
rrenkert@97: else if(type.equals("polygon") && elem.getTagName().equals("symbol")) {
rrenkert@97: FillStyleWriter swriter = new FillStyleWriter (this.map, co);
rrenkert@97: swriter.write (elem);
rrenkert@87: }
rrenkert@87: }
rrenkert@42: }
rrenkert@41: }
rrenkert@126:
vc11884admin@134:
vc11884admin@152: private String createExpression(Element ce, int index) {
rrenkert@137: String expression = "(";
rrenkert@137: int count = 0;
rrenkert@137: try {
rrenkert@137: count = Integer.parseInt(ce.getAttribute("field_count"));
rrenkert@137: }
rrenkert@137: catch(NumberFormatException nfe) {
rrenkert@137: return "";
rrenkert@137: }
rrenkert@137: if(count == 1) {
vc11884admin@134: try {
vc11884admin@134: Double.parseDouble(ce.getAttribute("value"));
rrenkert@137: String exp = ce.getAttribute("expression_field_0");
rrenkert@137: String pre = "";
rrenkert@137: if (!prefix.equals("") && !exp.startsWith(prefix)) {
vc11884admin@134: pre = prefix + ".";
rrenkert@137: }
rrenkert@137: expression += "[" + pre;
rrenkert@137: expression += ce.getAttribute("expression_field_0") + "]";
rrenkert@137: if(ce.hasAttribute("min_value")) {
vc11884admin@152: if(index == 0) {
vc11884admin@152: expression += " >= " + ce.getAttribute("min_value");
vc11884admin@152: }
vc11884admin@152: else {
vc11884admin@152: expression += " > " + ce.getAttribute("min_value");
vc11884admin@152: }
vc11884admin@169: expression += " AND [" + pre;
rrenkert@137: expression += ce.getAttribute("expression_field_0")+ "]";
rrenkert@137: }
rrenkert@137: expression += " " + ce.getAttribute("expression_operator");
rrenkert@137: expression += " " + ce.getAttribute("value") + ")";
rrenkert@137: }
rrenkert@137: catch(NumberFormatException nfe) {
rrenkert@137: String exp = ce.getAttribute("expression_field_0");
rrenkert@137: String pre = "";
rrenkert@137: if (!prefix.equals("") && !exp.startsWith(prefix)) {
vc11884admin@134: pre = prefix + ".";
rrenkert@137: }
rrenkert@137: expression += "\"[" + pre;
rrenkert@137: expression += ce.getAttribute("expression_field_0") + "]\"";
rrenkert@137: expression += " " + ce.getAttribute("expression_operator");
rrenkert@137: expression += " \"" + ce.getAttribute("value") + "\")";
rrenkert@137: }
rrenkert@137: catch(Exception e) {
rrenkert@137: e.printStackTrace();
rrenkert@137: }
rrenkert@137: }
rrenkert@137: else {
vc11884admin@134: for (int i = 0; i < count; i++) {
vc11884admin@134: try {
vc11884admin@134: Double.parseDouble(ce.getAttribute("value_" + i));
vc11884admin@134: String exp = ce.getAttribute("expression_field_" + i);
vc11884admin@134: String pre = "";
vc11884admin@134: if (!prefix.equals("") && !exp.startsWith(prefix)) {
vc11884admin@134: pre = prefix + ".";
vc11884admin@134: }
vc11884admin@134: expression += "[" + pre;
vc11884admin@134: expression += ce.getAttribute("expression_field_" + i) + "]";
vc11884admin@134: expression += " " + ce.getAttribute("expression_operator");
vc11884admin@134: expression += " " + ce.getAttribute("value_" + i);
rrenkert@137: if (i < count - 1) {
rrenkert@137: expression += " AND ";
rrenkert@137: }
rrenkert@137: else {
rrenkert@137: expression += ")";
rrenkert@137: }
rrenkert@137: }
rrenkert@137: catch (NumberFormatException nfe) {
rrenkert@137: String exp = ce.getAttribute("expression_field_" + i);
vc11884admin@134: String pre = "";
vc11884admin@134: if (!prefix.equals("") && !exp.startsWith(prefix)) {
vc11884admin@134: pre = prefix + ".";
vc11884admin@134: }
vc11884admin@134: expression += "\"[" + pre;
vc11884admin@134: expression += ce.getAttribute("expression_field_" + i) + "]\"";
vc11884admin@134: expression += " " + ce.getAttribute("expression_operator");
vc11884admin@134: expression += " " + ce.getAttribute("value_" + i);
rrenkert@137: if (i < count - 1) {
rrenkert@137: expression += " AND ";
rrenkert@137: }
rrenkert@137: else {
rrenkert@137: expression += ")";
rrenkert@137: }
rrenkert@126: }
rrenkert@126: }
rrenkert@126: }
rrenkert@137: return expression;
rrenkert@127: }
rrenkert@41: }
rrenkert@41: