]> git.argeo.org Git - gpl/argeo-suite.git/blob - knowledge/org.argeo.support.odk/src/org/argeo/support/odk/OdkUtils.java
[maven-release-plugin] prepare for next development iteration
[gpl/argeo-suite.git] / knowledge / org.argeo.support.odk / src / org / argeo / support / odk / OdkUtils.java
1 package org.argeo.support.odk;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.URI;
7 import java.net.URISyntaxException;
8
9 import javax.jcr.ImportUUIDBehavior;
10 import javax.jcr.Node;
11 import javax.jcr.NodeIterator;
12 import javax.jcr.Property;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15 import javax.jcr.nodetype.NodeType;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.argeo.entity.EntityType;
20 import org.argeo.jcr.Jcr;
21 import org.argeo.jcr.JcrUtils;
22 import org.argeo.jcr.JcrxApi;
23 import org.argeo.util.DigestUtils;
24
25 /** Utilities around ODK. */
26 public class OdkUtils {
27 private final static Log log = LogFactory.getLog(OdkUtils.class);
28
29 public static void loadOdkForm(Node formBase, String name, InputStream in) throws RepositoryException, IOException {
30 if (!formBase.isNodeType(EntityType.formSet.get()))
31 throw new IllegalArgumentException(
32 "Parent path " + formBase + " must be of type " + EntityType.formSet.get());
33 Node form = JcrUtils.getOrAdd(formBase, name, OrxListName.xform.get(), NodeType.MIX_VERSIONABLE);
34
35 String previousCsum = JcrxApi.getChecksum(form, JcrxApi.MD5);
36 String previousFormId = Jcr.get(form, OrxListName.formID.get());
37 String previousFormVersion = Jcr.get(form, OrxListName.version.get());
38
39 Session s = formBase.getSession();
40 // String res = "/odk/apafSession.odk.xml";
41 // try (InputStream in = getClass().getClassLoader().getResourceAsStream(res)) {
42 s.importXML(form.getPath(), in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
43 // }
44
45 // manage instances
46 // NodeIterator instances =
47 // form.getNodes("h:html/h:head/xforms:model/xforms:instance");
48 NodeIterator instances = form.getNode("h:html/h:head/xforms:model").getNodes("xforms:instance");
49 Node primaryInstance = null;
50 while (instances.hasNext()) {
51 Node instance = instances.nextNode();
52 if (primaryInstance == null) {
53 primaryInstance = instance;
54 } else {// secondary instances
55 String instanceId = instance.getProperty("id").getString();
56 URI instanceUri = null;
57 if (instance.hasProperty("src"))
58 try {
59 instanceUri = new URI(instance.getProperty("src").getString());
60 } catch (URISyntaxException e) {
61 throw new IllegalArgumentException("Instance " + instanceId + " has a badly formatted URI", e);
62 }
63 if (instanceUri != null) {
64 if ("jr".equals(instanceUri.getScheme())) {
65 String type = instanceUri.getHost();
66 if ("file".equals(type)) {
67 Node manifest = JcrUtils.getOrAdd(form, OrxManifestName.manifest.name(),
68 OrxManifestName.manifest.get());
69 Node file = JcrUtils.getOrAdd(manifest, instanceId);
70 String path = instanceUri.getPath();
71 if (!path.endsWith(".xml"))
72 throw new IllegalArgumentException("File uri " + instanceUri + " must end with .xml");
73 path = path.substring(0, path.length() - ".xml".length());
74 Node target = file.getSession().getNode(path);
75 if (target.isNodeType(NodeType.MIX_REFERENCEABLE)) {
76 file.setProperty(Property.JCR_ID, target);
77 if (file.hasProperty(Property.JCR_PATH))
78 file.getProperty(Property.JCR_PATH).remove();
79 } else {
80 file.setProperty(Property.JCR_PATH, target.getPath());
81 if (file.hasProperty(Property.JCR_ID))
82 file.getProperty(Property.JCR_ID).remove();
83 }
84 }
85 }
86 }
87 }
88 }
89
90 if (primaryInstance == null)
91 throw new IllegalArgumentException("No primary instance found in " + form);
92 if (!primaryInstance.hasNodes())
93 throw new IllegalArgumentException("No data found in primary instance of " + form);
94 NodeIterator primaryInstanceChildren = primaryInstance.getNodes();
95 Node data = primaryInstanceChildren.nextNode();
96 if (primaryInstanceChildren.hasNext())
97 throw new IllegalArgumentException("More than one data found in primary instance of " + form);
98 String formId = data.getProperty("id").getString();
99 if (previousFormId != null && !formId.equals(previousFormId))
100 log.warn("Form id of " + form + " changed from " + previousFormId + " to " + formId);
101 form.setProperty(OrxListName.formID.get(), formId);
102 String formVersion = data.getProperty("version").getString();
103
104 if (previousCsum == null)// save before checksuming
105 s.save();
106 String newCsum;
107 try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
108 s.exportDocumentView(form.getPath() + "/" + OdkNames.H_HTML, out, true, false);
109 newCsum = DigestUtils.digest(DigestUtils.MD5, out.toByteArray());
110 }
111 if (previousCsum == null) {
112 JcrxApi.addChecksum(form, newCsum);
113 JcrUtils.updateLastModified(form);
114 form.setProperty(OrxListName.version.get(), formVersion);
115 s.save();
116 s.getWorkspace().getVersionManager().checkpoint(form.getPath());
117 if (log.isDebugEnabled())
118 log.debug("New form " + form);
119 } else {
120 if (newCsum.equals(previousCsum)) {
121 // discard
122 s.refresh(false);
123 if (log.isDebugEnabled())
124 log.debug("Unmodified form " + form);
125 return;
126 } else {
127 if (formVersion.equals(previousFormVersion)) {
128 s.refresh(false);
129 throw new IllegalArgumentException("Form " + form + " has been changed but version " + formVersion
130 + " has not been changed, discarding changes...");
131 }
132 form.setProperty(OrxListName.version.get(), formVersion);
133 JcrxApi.addChecksum(form, newCsum);
134 JcrUtils.updateLastModified(form);
135 s.save();
136 s.getWorkspace().getVersionManager().checkpoint(form.getPath());
137 if (log.isDebugEnabled()) {
138 log.debug("Updated form " + form);
139 log.debug("Previous csum " + previousCsum);
140 log.debug("New csum " + newCsum);
141 }
142 }
143 }
144 }
145
146 /** Singleton. */
147 private OdkUtils() {
148
149 }
150
151 }