</dependency>
<!-- Argeo Knowledge -->
+ <dependency>
+ <groupId>org.argeo.suite</groupId>
+ <artifactId>org.argeo.support.xforms</artifactId>
+ <version>2.1.16-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.argeo.suite</groupId>
<artifactId>org.argeo.support.odk</artifactId>
<version>2.1.16-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.argeo.suite</groupId>
+ <artifactId>org.argeo.support.geonames</artifactId>
+ <version>2.1.16-SNAPSHOT</version>
+ </dependency>
<!-- Base CMS distribution -->
<dependency>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.support.geonames</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.suite</groupId>
+ <artifactId>knowledge</artifactId>
+ <version>2.1.16-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.support.geonames</artifactId>
+ <name>Geonames support</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+package org.argeo.support.geonames;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+/** A Geonames administrative subdivision. */
+public class GeonamesAdm {
+ private final Long geonameId;
+ private final String countryCode;
+ private final String adminCode1;
+ private final String admLevel;
+ private final Integer level;
+ private final String name;
+ private final String asciiName;
+ private final List<String> alternateNames;
+ private final Double lat;
+ private final Double lng;
+ private final LocalDate lastUpdated;
+ private final ZoneId timeZone;
+
+ private final Long[] upperLevelIds = new Long[5];
+ private final List<GeonamesAdm> upperLevels = new ArrayList<>();
+
+ private List<String> row;
+
+ /** Initialise from a row in the main Geonames table. */
+ public GeonamesAdm(List<String> row) {
+ geonameId = Long.parseLong(row.get(0));
+ admLevel = row.get(7);
+ countryCode = row.get(8);
+ adminCode1 = row.get(10);
+ if (admLevel.startsWith("ADM")) {
+ if (admLevel.endsWith("H"))
+ level = Integer.parseInt(admLevel.substring(3, admLevel.length() - 1));
+ else
+ level = Integer.parseInt(admLevel.substring(3));
+ } else if (admLevel.equals("PCLI")) {
+ level = 0;
+ } else {
+ throw new IllegalArgumentException("Unsupported admin level " + admLevel);
+ }
+ name = row.get(1);
+ asciiName = row.get(2);
+ alternateNames = Arrays.asList(row.get(3).split(","));
+ lat = Double.parseDouble(row.get(4));
+ lng = Double.parseDouble(row.get(5));
+ lastUpdated = LocalDate.parse(row.get(18));
+ timeZone = ZoneId.of(row.get(17));
+ // upper levels
+ if (row.get(11) != null && !row.get(11).trim().equals(""))
+ upperLevelIds[2] = Long.parseLong(row.get(11));
+ if (row.get(12) != null && !row.get(12).trim().equals(""))
+ upperLevelIds[3] = Long.parseLong(row.get(12));
+ if (row.get(13) != null && !row.get(13).trim().equals(""))
+ upperLevelIds[4] = Long.parseLong(row.get(13));
+ this.row = row;
+ }
+
+ public void mapUpperLevels(Map<Long, GeonamesAdm> index) {
+ for (int i = 0; i < level; i++) {
+ Long geonameId = upperLevelIds[i];
+ upperLevels.add(i, index.get(geonameId));
+ }
+ }
+
+ public Long getGeonameId() {
+ return geonameId;
+ }
+
+ public Integer getLevel() {
+ return level;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getName(Function<String, String> transform) {
+ if (transform != null)
+ return transform.apply(name);
+ else
+ return name;
+
+ }
+
+ public String getAsciiName() {
+ return asciiName;
+ }
+
+ public List<String> getAlternateNames() {
+ return alternateNames;
+ }
+
+ public Double getLat() {
+ return lat;
+ }
+
+ public Double getLng() {
+ return lng;
+ }
+
+ public String getCountryCode() {
+ return countryCode;
+ }
+
+ public String getAdmLevel() {
+ return admLevel;
+ }
+
+ public List<String> getRow() {
+ return row;
+ }
+
+ public LocalDate getLastUpdated() {
+ return lastUpdated;
+ }
+
+ public ZoneId getTimeZone() {
+ return timeZone;
+ }
+
+ public String getAdminCode1() {
+ return adminCode1;
+ }
+
+ public Long[] getUpperLevelIds() {
+ return upperLevelIds;
+ }
+
+ public List<GeonamesAdm> getUpperLevels() {
+ return upperLevels;
+ }
+
+ @Override
+ public int hashCode() {
+ return geonameId.intValue();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof GeonamesAdm))
+ return false;
+ GeonamesAdm other = (GeonamesAdm) obj;
+ return geonameId.equals(other.geonameId);
+ }
+
+ @Override
+ public String toString() {
+ return name + " (ADM" + level + " " + geonameId + ")";
+ }
+
+}
--- /dev/null
+package org.argeo.support.geonames;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.argeo.util.CsvParser;
+import org.argeo.util.CsvWriter;
+
+/** Import GeoNames administrative division from the main table. */
+public class ImportGeonamesAdmin {
+ // private Log log = LogFactory.getLog(ImportGeonamesAdmin.class);
+ private Map<Long, GeonamesAdm> geonamesAdms = new HashMap<>();
+
+ /** Loads the data. */
+ public void parse(InputStream in) {
+ Map<String, Long> countryGeonameIds = new HashMap<>();
+ Map<String, Long> admin1GeonameIds = new HashMap<>();
+ CsvParser csvParser = new CsvParser() {
+
+ @Override
+ protected void processLine(Integer lineNumber, List<String> header, List<String> tokens) {
+ if (!"A".equals(tokens.get(6)))
+ return;
+ GeonamesAdm geonamesAdm = new GeonamesAdm(tokens);
+ geonamesAdms.put(geonamesAdm.getGeonameId(), geonamesAdm);
+ if (geonamesAdm.getAdmLevel().equals("PCLI"))
+ countryGeonameIds.put(geonamesAdm.getCountryCode(), geonamesAdm.getGeonameId());
+ if (geonamesAdm.getAdmLevel().equals("ADM1"))
+ admin1GeonameIds.put(geonamesAdm.getAdminCode1(), geonamesAdm.getGeonameId());
+ }
+ };
+ csvParser.setSeparator('\t');
+ csvParser.setNoHeader(true);
+ csvParser.parse(in, StandardCharsets.UTF_8);
+
+ // fill upper levels
+ for (GeonamesAdm adm : geonamesAdms.values()) {
+ adm.getUpperLevelIds()[0] = countryGeonameIds.get(adm.getCountryCode());
+ if (adm.getLevel() > 0)
+ adm.getUpperLevelIds()[1] = admin1GeonameIds.get(adm.getAdminCode1());
+ adm.mapUpperLevels(geonamesAdms);
+ }
+
+ }
+
+ public Map<Long, GeonamesAdm> getGeonamesAdms() {
+ return geonamesAdms;
+ }
+
+ /**
+ * Copies only the Geonames of feature class 'A' (administrative subdivisions).
+ */
+ public static void filterGeonamesAdm(InputStream in, OutputStream out) {
+ CsvWriter csvWriter = new CsvWriter(out, StandardCharsets.UTF_8);
+ csvWriter.setSeparator('\t');
+ CsvParser csvParser = new CsvParser() {
+
+ @Override
+ protected void processLine(Integer lineNumber, List<String> header, List<String> tokens) {
+ if (tokens.size() < 7 || !"A".equals(tokens.get(6)))
+ return;
+ csvWriter.writeLine(tokens);
+ }
+ };
+ csvParser.setSeparator('\t');
+ csvParser.setNoHeader(true);
+ csvParser.parse(in, StandardCharsets.UTF_8);
+ }
+
+ public static void main(String[] args) throws IOException {
+// String country = "allCountries";
+ String country = "CI";
+// try (InputStream in = Files
+// .newInputStream(Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + ".txt"));
+// OutputStream out = Files.newOutputStream(
+// Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + "-adm.txt"))) {
+// ImportGeonamesAdmin.filterGeonamesAdm(in, out);
+// }
+ try (InputStream in = Files.newInputStream(
+ Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + "-adm.txt"))) {
+ ImportGeonamesAdmin importGeonamesAdmin = new ImportGeonamesAdmin();
+ importGeonamesAdmin.parse(in);
+ }
+ }
+
+}
<property name="osgi.http.whiteboard.servlet.pattern" type="String" value="/formList"/>
<property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=odkServletContext)"/>
<reference bind="addForm" cardinality="0..n" interface="org.argeo.support.odk.OdkForm" name="OdkForm" policy="dynamic" unbind="removeForm"/>
+ <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="static" target="(cn=odk)"/>
</scr:component>
<service>
<provide interface="javax.servlet.Servlet"/>
</service>
- <property name="osgi.http.whiteboard.servlet.pattern" type="String" value="/*.xml"/>
+ <property name="osgi.http.whiteboard.servlet.pattern" type="String" value="/form/*"/>
<property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=odkServletContext)"/>
<reference bind="addForm" cardinality="0..n" interface="org.argeo.support.odk.OdkForm" name="OdkForm" policy="dynamic" unbind="removeForm"/>
+ <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="static" target="(cn=odk)"/>
</scr:component>
<property name="osgi.http.whiteboard.servlet.pattern" type="String" value="/submission"/>
<property name="osgi.http.whiteboard.context.select" type="String" value="(osgi.http.whiteboard.context.name=odkServletContext)"/>
<property name="osgi.http.whiteboard.servlet.multipart.enabled" type="String" value="true"/>
+ <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="static" target="(cn=odk)"/>
</scr:component>
-Import-Package:\
-org.osgi.service.http.context,\
-*
+Require-Capability:\
+cms.datamodel;filter:="(name=entity)",\
+cms.datamodel;filter:="(name=xforms)"
+
+Provide-Capability:\
+cms.datamodel; name=odk; cnd=/org/argeo/support/odk/odk.cnd
Service-Component:\
OSGI-INF/odkServletContext.xml,\
OSGI-INF/odkFormListServlet.xml,\
OSGI-INF/odkFormServlet.xml,\
OSGI-INF/odkSubmissionServlet.xml
+
+Import-Package:\
+org.osgi.service.http.context,\
+org.argeo.api,\
+*
<packaging>jar</packaging>
<dependencies>
<dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.cms</artifactId>
- <version>${version.argeo-commons}</version>
+ <groupId>org.argeo.suite</groupId>
+ <artifactId>org.argeo.suite.core</artifactId>
+ <version>2.1.16-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
--- /dev/null
+package org.argeo.support.odk;
+
+/** Names related to ODK. */
+public interface OdkNames {
+
+ public final static String H_HTML = "h:html";
+}
--- /dev/null
+package org.argeo.support.odk;
+
+import org.argeo.entity.JcrName;
+
+/** Types related to the http://openrosa.org/xforms/xformsList namespace. */
+public enum OrxListType implements JcrName {
+ xform;
+
+ @Override
+ public String getPrefix() {
+ return prefix();
+ }
+
+ public static String prefix() {
+ return "orxList";
+ }
+
+ @Override
+ public String getNamespace() {
+ return namespace();
+ }
+
+ public static String namespace() {
+ return "http://openrosa.org/xforms/xformsList";
+ }
+
+}
--- /dev/null
+<jr = "http://openrosa.org/javarosa">
+<orx = "http://openrosa.org/xforms">
+<orxList = "http://openrosa.org/xforms/xformsList">
+<orxManifest = "http://openrosa.org/xforms/xformsManifest">
+<odk = "http://www.opendatakit.org/xforms">
+
+[orxList:xform] > mix:created, mix:lastModified, jcrx:csum, entity:form
++ h:html (odk:html) = odk:html
+
+[odk:head]
++ h:title (jcrx:xmlvalue) = jcrx:xmlvalue
++ xforms:model (odk:model) = odk:model
+
+[odk:body] > xforms:ui
+
+
+[odk:html] > mix:referenceable
++ h:head (odk:head) = odk:head
++ h:body (odk:body) = odk:body
+
+[odk:model] > xforms:model
++ odk:setgeopoint (odk:setgeopoint) = odk:setgeopoint
++ xforms:itext (odk:itext) = odk:itext
+
+[odk:itext]
++ xforms:translation (odk:translation) = odk:translation *
+
+[odk:translation]
+- lang (STRING) m
+- default (STRING)
++ xforms:text (odk:text) = odk:text *
+
+[odk:text]
+- id (STRING) m
++ xforms:value (jcrx:xmlvalue) = jcrx:xmlvalue
+
+[odk:setgeopoint]
+- event (STRING)
+- ref (STRING)
import java.io.IOException;
import java.io.Writer;
+import java.security.AccessControlContext;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import javax.security.auth.Subject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.argeo.api.NodeConstants;
+import org.argeo.cms.servlet.ServletAuthUtils;
+import org.argeo.entity.EntityType;
+import org.argeo.jcr.Jcr;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.JcrxApi;
import org.argeo.support.odk.OdkForm;
+import org.argeo.support.odk.OrxListType;
/** Lists available forms. */
public class OdkFormListServlet extends HttpServlet {
private Set<OdkForm> odkForms = Collections.synchronizedSet(new HashSet<>());
+ private DateTimeFormatter versionFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd-HHmm")
+ .withZone(ZoneId.from(ZoneOffset.UTC));
+
+ private Repository repository;
+
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/xml; charset=utf-8");
int serverPort = req.getServerPort();
String protocol = serverPort == 443 || req.isSecure() ? "https" : "http";
+ String pathInfo = req.getPathInfo();
+
+ Subject subject = Subject
+ .getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName()));
+ log.debug("SERVLET CONTEXT: " + subject);
+
+ Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, NodeConstants.SYS_WORKSPACE), req);
+// session = NodeUtils.openDataAdminSession(repository, NodeConstants.SYS_WORKSPACE);
Writer writer = resp.getWriter();
writer.append("<?xml version='1.0' encoding='UTF-8' ?>");
writer.append("<xforms xmlns=\"http://openrosa.org/xforms/xformsList\">");
- for (OdkForm form : odkForms) {
- StringBuilder sb = new StringBuilder();
- sb.append("<xform>");
- sb.append("<formID>" + form.getFormId() + "</formID>");
- sb.append("<name>" + form.getName() + "</name>");
- sb.append("<version>" + form.getVersion() + "</version>");
- sb.append("<hash>" + form.getHash(null) + "</hash>");
- sb.append("<descriptionText>" + form.getDescription() + "</descriptionText>");
- sb.append("<downloadUrl>" + protocol + "://" + serverName
- + (serverPort == 80
- || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/" + form.getFileName()
- + "</downloadUrl>");
- sb.append("</xform>");
- String str = sb.toString();
- if (log.isDebugEnabled())
- log.debug(str);
- writer.append(str);
+ boolean oldApproach = false;
+ if (oldApproach) {
+ try {
+
+ Query query;
+ if (pathInfo == null) {
+// query = session.getWorkspace().getQueryManager()
+// .createQuery("SELECT * FROM [nt:unstructured]", Query.JCR_SQL2);
+ query = session.getWorkspace().getQueryManager()
+ .createQuery("SELECT * FROM [" + OrxListType.xform.get() + "]", Query.JCR_SQL2);
+ } else {
+ query = session.getWorkspace().getQueryManager()
+ .createQuery(
+ "SELECT node FROM [" + OrxListType.xform.get()
+ + "] AS node WHERE ISDESCENDANTNODE (node, '" + pathInfo + "')",
+ Query.JCR_SQL2);
+ }
+ QueryResult queryResult = query.execute();
+
+ NodeIterator nit = queryResult.getNodes();
+// log.debug(session.getUserID());
+// log.debug(session.getWorkspace().getName());
+// NodeIterator nit = session.getRootNode().getNodes();
+// while (nit.hasNext()) {
+// log.debug(nit.nextNode());
+// }
+ while (nit.hasNext()) {
+ StringBuilder sb = new StringBuilder();
+ Node node = nit.nextNode();
+ if (node.isNodeType(OrxListType.xform.get())) {
+ sb.append("<xform>");
+ sb.append("<formID>" + node.getNode("h:html").getIdentifier() + "</formID>");
+ sb.append("<name>" + Jcr.getTitle(node) + "</name>");
+ sb.append("<version>" + versionFormatter.format(JcrUtils.getModified(node)) + "</version>");
+ sb.append("<hash>md5:" + JcrxApi.getChecksum(node, JcrxApi.MD5) + "</hash>");
+ if (node.hasProperty(Property.JCR_DESCRIPTION))
+ sb.append("<name>" + node.getProperty(Property.JCR_DESCRIPTION).getString() + "</name>");
+ sb.append("<downloadUrl>" + protocol + "://" + serverName
+ + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/form/"
+ + node.getPath() + "</downloadUrl>");
+ sb.append("</xform>");
+ } else if (node.isNodeType(EntityType.formSet.get())) {
+ sb.append("<xforms-group>");
+ sb.append("<groupId>" + node.getPath() + "</groupId>");
+ sb.append("<name>" + node.getProperty(Property.JCR_TITLE).getString() + "</name>");
+ sb.append("<listUrl>" + protocol + "://" + serverName
+ + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/formList"
+ + node.getPath() + "</listUrl>");
+ sb.append("</xforms-group>");
+ }
+ String str = sb.toString();
+ if (!str.equals("")) {
+ if (log.isDebugEnabled())
+ log.debug(str);
+ writer.append(str);
+ }
+ }
+ } catch (RepositoryException e) {
+ e.printStackTrace();
+ // TODO error message
+ // resp.sendError(500);
+ } finally {
+ Jcr.logout(session);
+ }
+
+ } else {
+ for (OdkForm form : odkForms) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<xform>");
+ sb.append("<formID>" + form.getFormId() + "</formID>");
+ sb.append("<name>" + form.getName() + "</name>");
+ sb.append("<version>" + form.getVersion() + "</version>");
+ sb.append("<hash>" + form.getHash(null) + "</hash>");
+ sb.append("<descriptionText>" + form.getDescription() + "</descriptionText>");
+ sb.append("<downloadUrl>" + protocol + "://" + serverName
+ + (serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) + "/api/odk/form/"
+ + form.getFileName() + "</downloadUrl>");
+ sb.append("</xform>");
+ String str = sb.toString();
+ if (log.isDebugEnabled())
+ log.debug(str);
+ writer.append(str);
+ }
}
writer.append("</xforms>");
}
public void removeForm(OdkForm odkForm) {
odkForms.remove(odkForm);
}
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
}
import java.util.HashMap;
import java.util.Map;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FilenameUtils;
+import org.argeo.cms.servlet.ServletAuthUtils;
+import org.argeo.jcr.Jcr;
import org.argeo.support.odk.OdkForm;
+import org.argeo.support.odk.OdkNames;
/** Retrieves a single form. */
public class OdkFormServlet extends HttpServlet {
private static final long serialVersionUID = 7838305967987687370L;
+ private Repository repository;
private Map<String, OdkForm> odkForms = Collections.synchronizedMap(new HashMap<>());
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/xml; charset=utf-8");
- String path = req.getServletPath();
- String fileName = FilenameUtils.getName(path);
- OdkForm form = odkForms.get(fileName);
- if (form == null)
- throw new IllegalArgumentException("No form named " + fileName + " was found");
-
- byte[] buffer = new byte[1024];
- try (InputStream in = form.openStream(); OutputStream out = resp.getOutputStream();) {
- int bytesRead;
- while ((bytesRead = in.read(buffer)) != -1)
- out.write(buffer, 0, bytesRead);
+ Session session = ServletAuthUtils.doAs(() -> Jcr.login(repository, null), req);
+
+ String pathInfo = req.getPathInfo();
+
+ boolean oldApproach = false;
+ try {
+ if (!oldApproach) {
+ session.exportDocumentView(pathInfo + "/" + OdkNames.H_HTML, resp.getOutputStream(), true, false);
+ } else {
+
+ String fileName = FilenameUtils.getName(pathInfo);
+ OdkForm form = odkForms.get(fileName);
+ if (form == null)
+ throw new IllegalArgumentException("No form named " + fileName + " was found");
+
+ byte[] buffer = new byte[1024];
+ try (InputStream in = form.openStream(); OutputStream out = resp.getOutputStream();) {
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) != -1)
+ out.write(buffer, 0, bytesRead);
+ }
+ }
+ } catch (RepositoryException e) {
+ e.printStackTrace();
+ // TODO error message
+ resp.sendError(500);
+ } finally {
+ Jcr.logout(session);
}
}
odkForms.remove(odkForm.getFileName());
}
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
}
import org.argeo.cms.servlet.PrivateWwwAuthServletContext;
+/** OSK specific authentication (with additional headers).*/
public class OdkServletContext extends PrivateWwwAuthServletContext {
@Override
import java.io.InputStream;
import java.io.StringWriter;
+import javax.jcr.Repository;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
private final static String XML_SUBMISSION_FILE = "xml_submission_file";
+ private Repository repository;
+
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
for (Part part : req.getParts()) {
+ "<message>Form Received!</message>" + "</OpenRosaResponse>");
}
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.support.xforms</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+Require-Capability:\
+cms.datamodel;filter:="(name=entity)"
+
+Provide-Capability:\
+cms.datamodel; name=xforms; cnd=/org/argeo/support/xforms/xforms.cnd
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.suite</groupId>
+ <artifactId>knowledge</artifactId>
+ <version>2.1.16-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.support.xforms</artifactId>
+ <name>XForms support</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.suite</groupId>
+ <artifactId>org.argeo.suite.core</artifactId>
+ <version>2.1.16-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+<xforms = "http://www.w3.org/2002/xforms">
+
+[xforms:model]
++ xforms:instance (xforms:instance) = xforms:instance *
++ xforms:bind (xforms:bind) = xforms:bind *
++ xforms:setvalue (xforms:setvalue) = xforms:setvalue *
+
+[xforms:instance] > nt:unstructured
+
+[xforms:bind]
+- * (STRING)
+
+[xforms:setvalue]
+- * (STRING)
+
+[xforms:select] > xforms:input
++ xforms:itemset (xforms:itemset) = xforms:itemset
+
+[xforms:itemset]
+- nodeset (STRING)
++ xforms:label (jcrx:xmlvalue) = jcrx:xmlvalue
++ xforms:value (jcrx:xmlvalue) = jcrx:xmlvalue
+
+[xforms:ui]
+- * (STRING)
++ xforms:label (jcrx:xmlvalue) = jcrx:xmlvalue *
++ xforms:hint (jcrx:xmlvalue) = jcrx:xmlvalue *
++ xforms:input (xforms:input) = xforms:input *
++ xforms:select (xforms:select) = xforms:select *
++ xforms:select1 (xforms:select) = xforms:select *
++ xforms:trigger (xforms:input) = xforms:input *
++ xforms:upload (xforms:input) = xforms:input *
++ xforms:group (xforms:ui) = xforms:ui *
++ xforms:repeat (xforms:ui) = xforms:ui *
+
+[xforms:input]
+- * (STRING)
++ xforms:label (jcrx:xmlvalue) = jcrx:xmlvalue
++ xforms:hint (jcrx:xmlvalue) = jcrx:xmlvalue *
--- /dev/null
+<xsd:schema targetNamespace="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" elementFormDefault="qualified">
+ <!--
+ Changes:
+26-Aug MJD fixed typo where more than one child allowed on <instance>
+04-Sep MJD fixed typo on <send> : attribute 'submission' is required
+04-Sep MJD fixed typo on <rebuild><recalculate><revalidate><refresh>: 'model' attribute is required
+06-Sep MJD clarified specific allowed values of @level on <message>
+06-Sep MJD removed UI Common attributes from <help><hint><alert><label>
+09-Sep MJD changed minOccurrs and maxOccurs to use XPath expressions, default values
+09-Sep MJD fixed typo: added linking attributes to <message>
+09-Sep MJD removed <extension> from content models of <mode> and UI common elements
+09-Sep MJD fixed typo: removed 'format' attribute
+17-Sep MJD fixed typo: <output> now uses the attribute group for binding attributes, instead of similarly named individual attrs
+17-Sep MJD added XPathExpression simpleType for internal use. This doesn't actually change anything, but makes
+the Schema a better documentation resource (instead of using xsd:string for everything)
+17-Sep MJD removed 'mediatype' attribute from <submission>, as it was unused
+17-Sep MJD fixed typo: only 'ref' and 'bind' attributes, not 'model' on <submission>
+17-Sep MJD added XML Events attributes to <model>
+17-Sep MJD in accordance with 3.2.1, removed all id attributes
+19-Sep MJD fixed typo: clarified that nested <action>s are permitted.
+19-Sep MJD factor UI.Inline into <group>. Renamed <group>s and <attributeGroup>s to match the prose names
+19-Sep MJD changed to agreed-upon namespace for CR
+25-Sep MJD fixed typo: added UI.Inlne to content model of <message>, enabled mixed content
+29-Sep MJD fixed typo: 'model' required on <reset>
+29-Sep MJD fixed typo: binding attributes allowed on <submit>
+29-Sep MJD fixed typo: explicit enumerated values for 'show' on <load>
+04-Oct MJD 'resource' attribute not required
+
+12-Nov 2002 : Published as CR
+
+13-Jan MJD added new attribute includenamespaceprefixes on <submission>
+13-Jan MJD added UI Common elements to content model of <group>
+03-Feb MJD synchoninzed duration types with 15 Nov Query Operators document
+31-Mar MJD added mediatype attribute on <submission>
+14-May MJD typo : "xsd:NCName"
+26-Jun MJD removed 'accesskey' and 'navindex' (over to host language definition)
+
+01-Aug 2003 : Published as PR
+
+15-Sep MJD final namespace
+15-Sep MJD corrected content model of <value>
+15-Sep MJD changed the name of the import for XML Events to highlight that only the attributes are used
+
+1.0 Second Edition errata
+
+16-Apr 2005 RAM - erratum E4 - optional @model
+16-Apr 2005 RAM - erratum E22 - default value for @show
+16-Apr 2005 RAM - erratum E54 - remove xforms:minOccurs and xforms:maxOccurs
+26-Jun 2005 RAM - erratum E71 - allow an empty case element
+
+16-Jun 2006 JMB - erratum E69 - instance attribute in submission; id in common attributes
+
+15-Aug-2006 CFW - erratum E18 on 2nd ed. Added Action to content model for Case
+
+09-Sep 2006 JMB - non-substantive: explicitly declared some use="optional" settings,
+ substantive: erratum E18 on 2nd ed. Declared default false for selected attribute of case
+ substantive: erratum E21 on 2nd ed. Added multipart-post to enumeration of method attribute
+23-Nov 2006 JMB - substantive: erratum E32 on 2nd ed. switch in repeat
+17-Jul 2007 JMB - substantive: erratum E41 on 2nd ed. version attribute and associated simple types
+-->
+ <xsd:import namespace="http://www.w3.org/2001/xml-events" schemaLocation="http://www.w3.org/MarkUp/SCHEMA/xml-events-attribs-1.xsd"/>
+ <xsd:import namespace="http://www.w3.org/2001/XMLSchema" schemaLocation="http://www.w3.org/2001/XMLSchema.xsd"/>
+ <!--
+structural elements
+-->
+ <xsd:attributeGroup name="Common.Attributes">
+ <xsd:annotation>
+ <xsd:documentation>Attributes for _every_ element in XForms</xsd:documentation>
+ </xsd:annotation>
+ <xsd:attribute name="id" type="xsd:ID" use="optional"/>
+ <xsd:anyAttribute namespace="##other"/>
+ </xsd:attributeGroup>
+ <xsd:element name="model">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:choice>
+ <xsd:element ref="xforms:instance"/>
+ <xsd:element ref="xsd:schema"/>
+ <xsd:element ref="xforms:submission"/>
+ <xsd:element ref="xforms:bind"/>
+ <xsd:group ref="xforms:Action"/>
+ </xsd:choice>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ <xsd:attribute name="functions" type="xforms:QNameList" use="optional"/>
+ <xsd:attribute name="schema" type="xforms:anyURIList" use="optional"/>
+ <xsd:attribute name="version" type="xforms:versionList" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="instance">
+ <xsd:annotation>
+ <xsd:documentation>instance container.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="skip" minOccurs="0"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="submission">
+ <xsd:annotation>
+ <xsd:documentation>submit info container.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:group ref="xforms:Action"/>
+ </xsd:sequence>
+
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+
+ <xsd:attribute name="ref" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="bind" type="xsd:IDREF" use="optional"/>
+ <xsd:attribute name="action" type="xsd:anyURI" use="optional"/>
+
+ <xsd:attribute name="method" use="required">
+ <xsd:simpleType>
+ <xsd:union memberTypes="xforms:QNameButNotNCNAME">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="post"/>
+ <xsd:enumeration value="put"/>
+ <xsd:enumeration value="get"/>
+ <xsd:enumeration value="multipart-post"/>
+ <xsd:enumeration value="form-data-post"/>
+ <xsd:enumeration value="urlencoded-post"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:attribute>
+
+ <xsd:attribute name="version" type="xsd:NMTOKEN" use="optional"/>
+ <xsd:attribute name="indent" type="xsd:boolean" use="optional"/>
+ <xsd:attribute name="mediatype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="encoding" type="xsd:string" use="optional"/>
+ <xsd:attribute name="omit-xml-declaration" type="xsd:boolean" use="optional"/>
+ <xsd:attribute name="standalone" type="xsd:boolean" use="optional"/>
+ <xsd:attribute name="cdata-section-elements" type="xforms:QNameList" use="optional"/>
+
+ <xsd:attribute name="replace" use="optional" default="all">
+ <xsd:simpleType>
+ <xsd:union memberTypes="xforms:QNameButNotNCNAME">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="all"/>
+ <xsd:enumeration value="instance"/>
+ <xsd:enumeration value="none"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:attribute>
+
+ <xsd:attribute name="instance" type="xsd:IDREF" use="optional"/>
+
+ <xsd:attribute name="separator" use="optional" default=";">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value=";"/>
+ <xsd:enumeration value="&"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+
+ <xsd:attribute name="includenamespaceprefixes" use="optional">
+ <xsd:simpleType>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:union>
+ <xsd:simpleType>
+ <xsd:restriction base='xsd:NCName'/>
+ </xsd:simpleType>
+ <xsd:simpleType>
+ <xsd:restriction base='xsd:string'>
+ <xsd:enumeration value='#default'/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ </xsd:attribute>
+
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:attributeGroup name="Linking.Attributes">
+ <xsd:attribute name="src" type="xsd:anyURI"/>
+ </xsd:attributeGroup>
+ <xsd:element name="bind">
+ <xsd:annotation>
+ <xsd:documentation>Definition of bind container.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="xforms:bind"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="nodeset" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="type" type="xsd:QName" use="optional"/>
+ <xsd:attribute name="readonly" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="required" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="relevant" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="constraint" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="calculate" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="p3ptype" type="xsd:string" use="optional"/>
+ <!-- E54 -->
+ </xsd:complexType>
+ </xsd:element>
+ <!--
+User Interface form controls
+-->
+ <xsd:group name="Form.Controls">
+ <xsd:choice>
+ <xsd:element ref="xforms:input"/>
+ <xsd:element ref="xforms:textarea"/>
+ <xsd:element ref="xforms:secret"/>
+ <xsd:element ref="xforms:output"/>
+ <xsd:element ref="xforms:upload"/>
+ <xsd:element ref="xforms:select1"/>
+ <xsd:element ref="xforms:select"/>
+ <xsd:element ref="xforms:range"/>
+ <xsd:element ref="xforms:submit"/>
+ <xsd:element ref="xforms:trigger"/>
+ </xsd:choice>
+ </xsd:group>
+ <xsd:attributeGroup name="Single.Node.Binding.Attributes">
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <xsd:attribute name="ref" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="bind" type="xsd:IDREF" use="optional"/>
+ </xsd:attributeGroup>
+ <xsd:attributeGroup name="Nodeset.Binding.Attributes">
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <xsd:attribute name="nodeset" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attribute name="bind" type="xsd:IDREF" use="optional"/>
+ </xsd:attributeGroup>
+ <xsd:attributeGroup name="UI.Common.Attrs">
+ <xsd:attribute name="appearance" type="xforms:appearanceType" use="optional"/>
+ </xsd:attributeGroup>
+ <xsd:group name="UI.Inline">
+ <xsd:sequence>
+ <xsd:choice minOccurs="0">
+ <xsd:element ref="xforms:output"/>
+ <!-- containing document language to add additional allowed content here -->
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:group>
+ <xsd:element name="label">
+ <xsd:complexType mixed="true">
+ <xsd:group ref="xforms:UI.Inline"/>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="hint">
+ <xsd:complexType mixed="true">
+ <xsd:group ref="xforms:UI.Inline"/>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="help">
+ <xsd:complexType mixed="true">
+ <xsd:group ref="xforms:UI.Inline"/>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="alert">
+ <xsd:complexType mixed="true">
+ <xsd:group ref="xforms:UI.Inline"/>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="extension">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:any namespace="##other"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="choices">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label" minOccurs="0"/>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:choice>
+ <xsd:element ref="xforms:choices"/>
+ <xsd:element ref="xforms:item"/>
+ <xsd:element ref="xforms:itemset"/>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="value">
+ <xsd:complexType mixed="true">
+ <xsd:sequence>
+ <xsd:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="item">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:element ref="xforms:value"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="itemset">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:choice>
+ <xsd:element ref="xforms:value"/>
+ <xsd:element ref="xforms:copy"/>
+ </xsd:choice>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="copy">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="filename">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="mediatype">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:group name="UI.Common">
+ <xsd:sequence>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="xforms:help"/>
+ <xsd:element ref="xforms:hint"/>
+ <xsd:element ref="xforms:alert"/>
+ <xsd:group ref="xforms:Action"/>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:group>
+ <xsd:element name="input">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="inputmode" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="textarea">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="inputmode" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="secret">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="inputmode" type="xsd:string" use="optional"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="upload">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:element ref="xforms:filename" minOccurs="0"/>
+ <xsd:element ref="xforms:mediatype" minOccurs="0"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="mediatype" type="xsd:string" use="optional"/>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:group name="List.UI.Common">
+ <xsd:sequence>
+ <xsd:choice>
+ <xsd:element ref="xforms:item"/>
+ <xsd:element ref="xforms:itemset"/>
+ <xsd:element ref="xforms:choices"/>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:group>
+ <xsd:element name="select1">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:List.UI.Common" maxOccurs="unbounded"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="selection" use="optional" default="closed">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="open"/>
+ <xsd:enumeration value="closed"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="true"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="select">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:List.UI.Common" maxOccurs="unbounded"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="selection" use="optional" default="closed">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="open"/>
+ <xsd:enumeration value="closed"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="true"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="range">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="start" type="xsd:string" use="optional"/>
+ <xsd:attribute name="end" type="xsd:string" use="optional"/>
+ <xsd:attribute name="step" type="xsd:string" use="optional"/>
+ <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="trigger">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="output">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0">
+ <xsd:element ref="xforms:label"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="appearance" type="xforms:appearanceType" use="optional"/>
+ <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="submit">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label"/>
+ <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="submission" type="xsd:IDREF" use="required"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ </xsd:complexType>
+ </xsd:element>
+ <!--
+XForms Actions
+-->
+ <xsd:attributeGroup name="XML.Events">
+ <xsd:attribute ref="ev:event"/>
+ <xsd:attribute ref="ev:observer"/>
+ <xsd:attribute ref="ev:target"/>
+ <xsd:attribute ref="ev:handler"/>
+ <xsd:attribute ref="ev:phase"/>
+ <xsd:attribute ref="ev:propagate"/>
+ <xsd:attribute ref="ev:defaultAction"/>
+ </xsd:attributeGroup>
+ <xsd:group name="Action">
+ <xsd:sequence>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="xforms:action"/>
+ <xsd:element ref="xforms:dispatch"/>
+ <xsd:element ref="xforms:rebuild"/>
+ <xsd:element ref="xforms:recalculate"/>
+ <xsd:element ref="xforms:revalidate"/>
+ <xsd:element ref="xforms:refresh"/>
+ <xsd:element ref="xforms:setfocus"/>
+ <xsd:element ref="xforms:load"/>
+ <xsd:element ref="xforms:setvalue"/>
+ <xsd:element ref="xforms:send"/>
+ <xsd:element ref="xforms:reset"/>
+ <xsd:element ref="xforms:insert"/>
+ <xsd:element ref="xforms:delete"/>
+ <xsd:element ref="xforms:setindex"/>
+ <xsd:element ref="xforms:toggle"/>
+ <xsd:element ref="xforms:message"/>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:group>
+ <xsd:element name="action">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:group ref="xforms:Action"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="dispatch">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="name" type="xsd:NMTOKEN" use="required"/>
+ <xsd:attribute name="target" type="xsd:IDREF" use="required"/>
+ <xsd:attribute name="bubbles" type="xsd:boolean" use="optional" default="true"/>
+ <xsd:attribute name="cancelable" type="xsd:boolean" use="optional" default="true"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="rebuild">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ <!-- E4 -->
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="revalidate">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ <!-- E4 -->
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="recalculate">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ <!-- E4 -->
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="refresh">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ <!-- E4 -->
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="setfocus">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="control" type="xsd:IDREF" use="required"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="load">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="resource" type="xsd:anyURI"/>
+ <xsd:attribute name="show" use="optional" default="replace">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="new"/>
+ <xsd:enumeration value="replace"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <!-- E22 -->
+ </xsd:attribute>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="setvalue">
+ <xsd:complexType>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="send">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="submission" type="xsd:IDREF" use="required"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="reset">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
+ <!-- E4 -->
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="insert">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
+ <xsd:attribute name="at" type="xforms:XPathExpression" use="required"/>
+ <xsd:attribute name="position" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="before"/>
+ <xsd:enumeration value="after"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="delete">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
+ <xsd:attribute name="at" type="xforms:XPathExpression" use="required"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="setindex">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="repeat" type="xsd:IDREF" use="required"/>
+ <xsd:attribute name="index" type="xforms:XPathExpression" use="required"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="toggle">
+ <xsd:complexType>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attribute name="case" type="xsd:IDREF" use="required"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="message">
+ <xsd:complexType mixed="true">
+ <xsd:group ref="xforms:UI.Inline"/>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attribute name="level" use="required">
+ <xsd:simpleType>
+ <xsd:union memberTypes="xforms:QNameButNotNCNAME">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="ephemeral"/>
+ <xsd:enumeration value="modeless"/>
+ <xsd:enumeration value="modal"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
+ <xsd:attributeGroup ref="xforms:XML.Events"/>
+ </xsd:complexType>
+ </xsd:element>
+ <!--
+Advanced User Interface
+-->
+ <xsd:attribute name="repeat-nodeset" type="xforms:XPathExpression"/>
+ <xsd:attribute name="repeat-model" type="xsd:IDREF"/>
+ <xsd:attribute name="repeat-bind" type="xsd:IDREF"/>
+ <xsd:attribute name="repeat-startindex" type="xsd:positiveInteger"/>
+ <xsd:attribute name="repeat-number" type="xsd:nonNegativeInteger"/>
+ <xsd:element name="repeat">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:choice>
+ <xsd:group ref="xforms:Form.Controls"/>
+ <xsd:element ref="xforms:group"/>
+ <xsd:element ref="xforms:switch"/>
+ <xsd:element ref="xforms:repeat"/>
+ <!-- containing document language to add additional allowed content here -->
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ <xsd:attribute name="startindex" type="xsd:positiveInteger"/>
+ <xsd:attribute name="number" type="xsd:nonNegativeInteger"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="group">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label" minOccurs="0"/>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:choice>
+ <xsd:group ref="xforms:UI.Common"/>
+ <xsd:group ref="xforms:Form.Controls"/>
+ <xsd:element ref="xforms:group"/>
+ <xsd:element ref="xforms:switch"/>
+ <xsd:element ref="xforms:repeat"/>
+ <!-- containing document language to add additional allowed content here -->
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="switch">
+ <xsd:complexType>
+ <xsd:sequence maxOccurs="unbounded">
+ <xsd:element ref="xforms:case"/>
+ </xsd:sequence>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
+ <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="case">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="xforms:label" minOccurs="0"/>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:choice>
+ <xsd:group ref="xforms:Form.Controls"/>
+ <xsd:group ref="xforms:Action"/>
+ <xsd:element ref="xforms:group"/>
+ <xsd:element ref="xforms:switch"/>
+ <xsd:element ref="xforms:repeat"/>
+ <!-- containing document language to add additional allowed content here -->
+ </xsd:choice>
+ <!-- E71 -->
+ </xsd:sequence>
+ </xsd:sequence>
+ <xsd:attribute name="selected" type="xsd:boolean" use="optional" default="false"/>
+ <xsd:attributeGroup ref="xforms:Common.Attributes"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!--
+New simpleTypes
+-->
+
+ <xsd:simpleType name="versionList">
+ <xsd:list itemType="xforms:versionNumber"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="versionNumber">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="[1-9]\d*\.\d+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="XPathExpression">
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="QNameList">
+ <xsd:list itemType="xsd:QName"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="anyURIList">
+ <xsd:list itemType="xsd:anyURI"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="QNameButNotNCNAME">
+ <xsd:restriction base="xsd:QName">
+ <xsd:pattern value="[^:]+:[^:]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="appearanceType">
+ <xsd:union memberTypes="xforms:QNameButNotNCNAME">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="full"/>
+ <xsd:enumeration value="compact"/>
+ <xsd:enumeration value="minimal"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:union>
+ </xsd:simpleType>
+ <xsd:simpleType name="listItem">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="\S+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="listItems">
+ <xsd:list itemType="xforms:listItem"/>
+ </xsd:simpleType>
+ <xsd:simpleType name="dayTimeDuration">
+ <xsd:restriction base="xsd:duration">
+ <xsd:pattern value="[\-]?P([0-9]+D(T([0-9]+(H([0-9]+(M([0-9]+(\.[0-9]*)?S
+ |\.[0-9]+S)?|(\.[0-9]*)?S)|(\.[0-9]*)?S)?|M([0-9]+
+ (\.[0-9]*)?S|\.[0-9]+S)?|(\.[0-9]*)?S)|\.[0-9]+S))?
+ |T([0-9]+(H([0-9]+(M([0-9]+(\.[0-9]*)?S|\.[0-9]+S)?
+ |(\.[0-9]*)?S)|(\.[0-9]*)?S)?|M([0-9]+(\.[0-9]*)?S|\.[0-9]+S)?
+ |(\.[0-9]*)?S)|\.[0-9]+S))"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+ <xsd:simpleType name="yearMonthDuration">
+ <xsd:restriction base="xsd:duration">
+ <xsd:pattern value="[\-]?P[0-9]+(Y([0-9]+M)?|M)"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+</xsd:schema>
<name>Argeo Knowledge Components</name>
<packaging>pom</packaging>
<modules>
+ <module>org.argeo.support.xforms</module>
<module>org.argeo.support.odk</module>
+ <module>org.argeo.support.geonames</module>
</modules>
</project>
+Require-Capability:\
+cms.datamodel;filter:="(name=jcrx)"
Provide-Capability:\
cms.datamodel; name=entity; cnd=/org/argeo/entity/entity.cnd
/** Constants used to name entity structures. */
public interface EntityNames {
- final String ENTITY_DEFINITIONS_PATH = "/entity:entityDefinitions";
+ final String FORM_BASE = "form";
+ final String TERM_BASE = "term";
+
+ final String ENTITY_DEFINITIONS_PATH = "/entity";
+ @Deprecated
+ final String TYPOLOGIES_PATH = "/" + TERM_BASE;
+ /** Administrative units. */
+ final String ADM = "adm";
final String ENTITY_TYPE = "entity:type";
final String ENTITY_UID = "entity:uid";
+ final String ENTITY_NAME = "entity:name";
// GENERIC CONCEPTS
- /** The date which is clearly relevant for this entity. */
+ /** The language which is relevant. */
+ final String XML_LANG = "xml:lang";
+ /** The date which is relevant. */
final String ENTITY_DATE = "entity:date";
final String ENTITY_RELATED_TO = "entity:relatedTo";
final String SURNAME = LdapAttrs.sn.property();
final String EMAIL = LdapAttrs.mail.property();
+ final String OU = LdapAttrs.ou.property();
+
+ // WGS84
+ final String GEO_LAT = "geo:lat";
+ final String GEO_LONG = "geo:long";
+ final String GEO_ALT = "geo:alt";
}
--- /dev/null
+package org.argeo.entity;
+
+/** Types related to entities. */
+public enum EntityType implements JcrName {
+ // entity
+ entity, definition,
+ // typology
+ typologies, terms, term,
+ // form
+ form, formSet,
+ // ldap
+ person;
+
+ @Override
+ public String getPrefix() {
+ return prefix();
+ }
+
+ public static String prefix() {
+ return "entity";
+ }
+
+ @Override
+ public String getNamespace() {
+ return namespace();
+ }
+
+ public static String namespace() {
+ return "http://www.argeo.org/ns/entity";
+ }
+
+}
package org.argeo.entity;
/** Types related to entities. */
+@Deprecated
public interface EntityTypes {
final static String ENTITY_ENTITY = "entity:entity";
final static String ENTITY_DEFINITION = "entity:definition";
--- /dev/null
+package org.argeo.entity;
+
+/** Can be applied to {@link Enum}s in order to generate prefixed names. */
+public interface JcrName {
+ String name();
+
+ default String getPrefix() {
+ return null;
+ }
+
+ default String getNamespace() {
+ return null;
+ }
+
+ default String get() {
+ String prefix = getPrefix();
+ return prefix != null ? prefix + ":" + name() : name();
+ }
+
+ default String withNamespace() {
+ String namespace = getNamespace();
+ if (namespace == null)
+ throw new UnsupportedOperationException("No namespace is specified for " + getClass());
+ return "{" + namespace + "}" + name();
+ }
+}
-<ldap = 'http://www.argeo.org/ns/ldap'>
+// Standard namespaces
+<xsd = "http://www.w3.org/2001/XMLSchema">
+<h = "http://www.w3.org/1999/xhtml">
+// see https://www.w3.org/2003/01/geo/
+//<geo = "http://www.w3.org/2003/01/geo/wgs84_pos#">
+
+<ldap = "http://www.argeo.org/ns/ldap">
<entity = 'http://www.argeo.org/ns/entity'>
-[entity:entity] > mix:title, mix:created, mix:lastModified, mix:referenceable
+[entity:entity] > mix:created, mix:referenceable
mixin
//- entity:uid (String) m // an implementation dependent UID for each entity
//- entity:type (String) // the type of this entity
-[entity:definition] > entity:composite, mix:title, mix:created, mix:lastModified, mix:referenceable
-mixin
+//
+// ENTITY DEFINITION
+//
+[entity:definition] > entity:composite, mix:created, mix:lastModified, mix:referenceable
+//- entity:type (String) multiple
-[entity:part]
-mixin
+//[entity:part]
-[entity:reference]
-mixin
+//[entity:reference]
[entity:composite]
-mixin
orderable
-+ * (entity:part)
-+ * (entity:reference)
-+ * (entity:composite)
+//+ * (entity:part)
+//+ * (entity:reference)
+//+ * (entity:composite)
+
+//
+// TYPOLOGY
+//
+[entity:typologies]
++ * (entity:terms) = entity:terms
+
+[entity:term]
+orderable
++ * (entity:term) = entity:term *
+
+[entity:terms] > mix:referenceable
+orderable
++ * (entity:term) = entity:term *
+
+//
+// FORM
+//
+[entity:form]
+mixin
+
+[entity:formSet]
+mixin
// LDAP-LIKE ENTITIES
// A real person
[entity:person] > entity:entity
mixin
+- ldap:sn (String)
+- ldap:givenName (String)
defaultEditoryId = properties.get(EntityConstants.DEFAULT_EDITORY_ID);
String definitionPath = EntityNames.ENTITY_DEFINITIONS_PATH + '/' + type;
if (!adminSession.itemExists(definitionPath)) {
- Node entityDefinition = JcrUtils.mkdirs(adminSession, definitionPath);
- entityDefinition.addMixin(EntityTypes.ENTITY_DEFINITION);
+ Node entityDefinition = JcrUtils.mkdirs(adminSession, definitionPath, EntityTypes.ENTITY_DEFINITION);
+// entityDefinition.addMixin(EntityTypes.ENTITY_DEFINITION);
adminSession.save();
}
initJcr(adminSession);
<arguments>
</arguments>
</buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ds.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="Suite Maintenance Service">
+ <implementation class="org.argeo.suite.core.SuiteMaintenanceService"/>
+ <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="static" target="(cn=entity)"/>
+ <reference bind="setUserTransaction" cardinality="1..1" interface="javax.transaction.UserTransaction" name="UserTransaction" policy="static"/>
+ <reference bind="setUserAdmin" cardinality="1..1" interface="org.osgi.service.useradmin.UserAdmin" name="UserAdmin" policy="static"/>
+</scr:component>
+Service-Component:\
+OSGI-INF/maintenanceService.xml
Import-Package:\
+javax.transaction,\
+org.osgi.service.useradmin,\
+javax.jcr.nodetype,\
org.argeo.api,\
+org.argeo.entity,\
*
\ No newline at end of file
-source.. = src/
output.. = bin/
bin.includes = META-INF/,\
- .
+ .,\
+ OSGI-INF/
+source.. = src/
<artifactId>org.argeo.cms</artifactId>
<version>${version.argeo-commons}</version>
</dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.maintenance</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
</dependencies>
</project>
RankedObject<T> rankedObject = new RankedObject<>(object, properties);
if (!map.containsKey(key)) {
map.put(key, rankedObject);
- if (log.isDebugEnabled())
- log.debug(
+ if (log.isTraceEnabled())
+ log.trace(
"Added " + key + " as " + object.getClass().getName() + " with rank " + rankedObject.getRank());
return rankedObject;
} else {
RankedObject<T> current = map.get(key);
if (current.getRank() <= rankedObject.getRank()) {
map.put(key, rankedObject);
- if (log.isDebugEnabled())
- log.debug("Replaced " + key + " by " + object.getClass().getName() + " with rank "
+ if (log.isTraceEnabled())
+ log.trace("Replaced " + key + " by " + object.getClass().getName() + " with rank "
+ rankedObject.getRank());
return rankedObject;
} else {
--- /dev/null
+package org.argeo.suite.core;
+
+import java.io.IOException;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.entity.EntityNames;
+import org.argeo.entity.EntityType;
+import org.argeo.maintenance.AbstractMaintenanceService;
+
+/** Initialises an Argeo Suite backend. */
+public class SuiteMaintenanceService extends AbstractMaintenanceService {
+
+ @Override
+ public boolean prepareJcrTree(Session adminSession) throws RepositoryException, IOException {
+ boolean modified = false;
+ Node rootNode = adminSession.getRootNode();
+ if (!rootNode.hasNode(EntityNames.TERM_BASE)) {
+ rootNode.addNode(EntityNames.TERM_BASE, EntityType.typologies.get());
+ modified = true;
+ }
+ if (modified)
+ adminSession.save();
+ return modified;
+ }
+
+}