Refactor Argeo APIs
[gpl/argeo-suite.git] / org.argeo.app.servlet.odk / src / org / argeo / app / servlet / odk / OdkManifestServlet.java
index 245e0f22d11cf19d3679024e2c49ccf14926c48b..e5e2de6ebce277a157341a023da1472a8b675695 100644 (file)
@@ -29,14 +29,18 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.io.output.NullOutputStream;
-import org.argeo.app.api.EntityMimeType;
+import org.argeo.api.app.EntityMimeType;
+import org.argeo.api.app.EntityType;
+import org.argeo.api.app.WGS84PosName;
+import org.argeo.app.geo.GeoShapeUtils;
 import org.argeo.app.odk.OrxManifestName;
 import org.argeo.cms.auth.RemoteAuthUtils;
 import org.argeo.cms.servlet.ServletHttpRequest;
+import org.argeo.cms.servlet.ServletUtils;
+import org.argeo.cms.util.CsvWriter;
+import org.argeo.cms.util.DigestUtils;
 import org.argeo.jcr.Jcr;
 import org.argeo.jcr.JcrException;
-import org.argeo.util.CsvWriter;
-import org.argeo.util.DigestUtils;
 
 /** Describe additional files. */
 public class OdkManifestServlet extends HttpServlet {
@@ -53,9 +57,9 @@ public class OdkManifestServlet extends HttpServlet {
                if (pathInfo.startsWith("//"))
                        pathInfo = pathInfo.substring(1);
 
-               String serverName = req.getServerName();
-               int serverPort = req.getServerPort();
-               String protocol = serverPort == 443 || req.isSecure() ? "https" : "http";
+               // we force HTTPS since ODK Collect will fail anyhow when sending http
+               // cf. https://forum.getodk.org/t/authentication-for-non-https-schems/32967/4
+               StringBuilder baseServer = ServletUtils.getRequestUrlBase(req, true);
 
                Session session = RemoteAuthUtils.doAs(() -> Jcr.login(repository, null), new ServletHttpRequest(req));
 
@@ -91,24 +95,15 @@ public class OdkManifestServlet extends HttpServlet {
 
                                                        MessageDigest messageDigest = MessageDigest.getInstance(DigestUtils.MD5);
                                                        // TODO cache a temp file ?
-                                                       try (DigestOutputStream out = new DigestOutputStream(new NullOutputStream(),
+                                                       try (DigestOutputStream out = new DigestOutputStream(NullOutputStream.NULL_OUTPUT_STREAM,
                                                                        messageDigest)) {
                                                                writeMediaFile(out, target, mimeType, charset);
                                                                writer.append("<hash>");
-                                                               writer.append("md5sum:" + DigestUtils.encodeHexString(out.getMessageDigest().digest()));
+                                                               writer.append("md5sum:" + DigestUtils.toHexString(out.getMessageDigest().digest()));
                                                                writer.append("</hash>");
                                                        }
-
-//                                                     try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
-//                                                             session.exportDocumentView(target.getPath(), out, true, false);
-//                                                             String fileCsum = DigestUtils.digest(DigestUtils.MD5, out.toByteArray());
-//                                                             writer.append("<hash>");
-//                                                             writer.append("md5sum:" + fileCsum);
-//                                                             writer.append("</hash>");
-//                                                     }
-                                                       writer.append("<downloadUrl>" + protocol + "://" + serverName
-                                                                       + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort)
-                                                                       + "/api/odk/formManifest" + file.getPath() + "</downloadUrl>");
+                                                       writer.append("<downloadUrl>" + baseServer + "/api/odk/formManifest" + file.getPath()
+                                                                       + "</downloadUrl>");
                                                }
                                                writer.append("</mediaFile>");
                                        }
@@ -123,11 +118,6 @@ public class OdkManifestServlet extends HttpServlet {
                                        Node target = node.getProperty(Property.JCR_ID).getNode();
 
                                        writeMediaFile(resp.getOutputStream(), target, mimeType, charset);
-//                                     try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
-//                                             session.exportDocumentView(target.getPath(), out, true, false);
-//                                             System.out.println(new String(out.toByteArray(), StandardCharsets.UTF_8));
-//                                             resp.getOutputStream().write(out.toByteArray());
-//                                     }
                                } else {
                                        throw new IllegalArgumentException("Unsupported node " + node);
                                }
@@ -149,19 +139,46 @@ public class OdkManifestServlet extends HttpServlet {
                if (target.isNodeType(NodeType.NT_QUERY)) {
                        Query query = target.getSession().getWorkspace().getQueryManager().getQuery(target);
                        QueryResult queryResult = query.execute();
-                       String[] columnNames = queryResult.getColumnNames();
+                       List<String> columnNames = new ArrayList<>();
+                       for (String c : queryResult.getColumnNames()) {
+                               columnNames.add(c);
+                       }
+                       // TODO make it more configurable
+                       columnNames.add("display");
+                       columnNames.add("geometry");
+
                        if (EntityMimeType.XML.equals(mimeType)) {
                        } else if (EntityMimeType.CSV.equals(mimeType)) {
                                CsvWriter csvWriter = new CsvWriter(out, charset);
                                csvWriter.writeLine(columnNames);
                                RowIterator rit = queryResult.getRows();
-                               while (rit.hasNext()) {
-                                       Row row = rit.nextRow();
-                                       Value[] values = row.getValues();
-                                       List<String> lst = new ArrayList<>();
-                                       for (Value value : values) {
-                                               lst.add(value.getString());
+                               if (rit.hasNext()) {
+                                       while (rit.hasNext()) {
+                                               Row row = rit.nextRow();
+                                               Value[] values = row.getValues();
+                                               List<String> lst = new ArrayList<>();
+                                               for (Value value : values) {
+                                                       lst.add(value.getString());
+                                               }
+                                               // display
+                                               lst.add(row.getValue("name").getString() + " (" + row.getValue("label").getString() + ")");
+                                               Node field = row.getNode("geopoint");
+                                               if (field != null && field.isNodeType(EntityType.geopoint.get())) {
+                                                       double lat = field.getProperty(WGS84PosName.lat.get()).getDouble();
+                                                       double lon = field.getProperty(WGS84PosName.lon.get()).getDouble();
+                                                       double alt = field.hasProperty(WGS84PosName.alt.get())
+                                                                       ? field.getProperty(WGS84PosName.alt.get()).getDouble()
+                                                                       : Double.NaN;
+                                                       String geoshape = GeoShapeUtils.geoPointToGeoShape(lon, lat, alt);
+                                                       lst.add(geoshape);
+                                               }
+                                               csvWriter.writeLine(lst);
                                        }
+                               } else {
+                                       // corner case of an empty initial database
+                                       List<String> lst = new ArrayList<>();
+                                       for (int i = 0; i < columnNames.size(); i++)
+                                               lst.add("-");
                                        csvWriter.writeLine(lst);
                                }
                        }