001: /**
002: * generated by RDFReactor on 9:59 on 29.2005
003: */package org.ontoware.semversion;
004:
005: import java.net.URISyntaxException;
006: import java.util.ArrayList;
007: import java.util.Calendar;
008: import java.util.Date;
009: import java.util.HashSet;
010: import java.util.List;
011: import java.util.Set;
012:
013: import org.ontoware.rdf2go.model.Model;
014: import org.ontoware.rdf2go.model.node.URI;
015: import org.ontoware.rdfreactor.runtime.Bridge;
016: import org.ontoware.rdfreactor.runtime.RDFDataException;
017: import org.ontoware.semversion.impl.generated.RDFModel;
018: import org.slf4j.Logger;
019: import org.slf4j.LoggerFactory;
020:
021: /**
022: * A VersionedModel holds a version tree for an RDF model.
023: *
024: * @author voelkel
025: */
026: public class VersionedModel extends VersionedItem {
027:
028: private static Logger log = LoggerFactory
029: .getLogger(VersionedModel.class);
030:
031: private org.ontoware.semversion.impl.generated.VersionedModel vm;
032:
033: public VersionedModel(Model model, Session session, URI uri,
034: boolean write) {
035: super (model, session, uri);
036: this .vm = new org.ontoware.semversion.impl.generated.VersionedModel(
037: model, uri, write);
038: }
039:
040: public VersionedModel(
041: org.ontoware.semversion.impl.generated.VersionedModel vm,
042: Session session) {
043: super (vm.getModel(), session, vm.getResource().asURI());
044: this .vm = vm;
045: }
046:
047: // ///////////////////
048: // root
049:
050: private void addToBranch(Branch branch, Version leaf) {
051: branch.fromRootToRecent.add(branch.fromRootToRecent.size(),
052: leaf);
053: if (leaf.getFirstParent() != null)
054: addToBranch(branch, leaf.getFirstParent());
055: }
056:
057: /**
058: * internal: keep a reference to the Version
059: */
060: protected void addVersion(Version value) {
061: this .vm.addVersion(value.getReactorVersion());
062: }
063:
064: /**
065: * Convenience method for <code>
066: * commitRoot(Model root, String label, String comment, URI versionURI, URI provenance)
067: * </code>
068: */
069: public Version commitRoot(Model root, String label)
070: throws URISyntaxException {
071: assert getSemVersion() != null;
072: return commitRoot(root, label, "", getSemVersion()
073: .getTripleStore().newRandomUniqueURI(), null);
074: }
075:
076: // ////////////////////////////////
077: // version
078:
079: /**
080: * Commit the root version to the version tree.
081: *
082: * @param root
083: * @param comment
084: * may be null
085: * @param versionURI
086: * may not be null
087: * @param provenance
088: * @return a new Version with the content given in 'root'. The new version
089: * has the versionURI and a comment.
090: * @throws IllegalStateException
091: * if this VersionedModel has already a root version
092: */
093: public Version commitRoot(Model root, String label, String comment,
094: URI versionURI, URI provenance) {
095: assert root != null;
096: assert comment != null;
097: if (versionURI == null) {
098: throw new IllegalArgumentException(
099: "versionURI may not be null");
100: }
101:
102: if (getRoot() != null)
103: throw new IllegalStateException(
104: "You tried to commit a root model, but I have already one: "
105: + getRoot()
106: + " Method call ignored, continue using existing root.");
107: else {
108: // create Version proxy
109: Version version = new Version(getSemVersion()
110: .getMainModel(), getSession(), versionURI, true);
111:
112: // set all data
113: version.setLabel(label);
114: version.setComment(comment);
115: User user = getSession().getUser();
116: log.debug("user: " + user.getName());
117: assert user != null;
118: version.setUser(user);
119: version.setValid();
120: version.setCreationTime(Calendar.getInstance());
121: version.setContainer(this );
122: if (provenance != null)
123: version.setProvenance(provenance);
124:
125: // store content = create triple set & link
126: Model rootModel = getSemVersion().getTripleStore()
127: .addModelAndPersist(root);
128: rootModel.close();
129: URI rootModelURI = rootModel.getContextURI();
130: RDFModel rdfmodel = new RDFModel(getSemVersion()
131: .getMainModel(), rootModelURI, false);
132: version.setContent(rdfmodel);
133: version.setChangeCause("commit");
134:
135: // link version
136: assert version != null;
137: assert getRoot() == null : "found root: " + getRoot();
138: setRoot(version);
139: assert getRoot() != null;
140: addVersion(version);
141: assert getRoot() != null;
142: return version;
143: }
144: }
145:
146: /**
147: * Removes this VersionedModel and all versions in the version tree.
148: */
149: public void delete() {
150: // process versions
151: for (Version v : getAllVersions()) {
152: v.delete();
153: }
154: // Delete
155: org.ontoware.semversion.impl.generated.VersionedModel
156: .deleteAllProperties(vm.getModel(), vm.getResource());
157: }
158:
159: /**
160: * Debugging help. Dumps all content on System.out.
161: */
162: public void dump() {
163: StringBuffer buf = new StringBuffer();
164: buf.append("dump of versioned Model " + vm + "\n");
165: buf
166: .append("URI of Version\tlabel\tbranchlabel\tsuggestion\tparent\tnumber of children\n");
167: for (Version v : getAllVersions()) {
168: buf.append(v + "\t" + v.getLabel() + "\t"
169: + v.getBranchLabel() + "\t" + v.isSuggestion()
170: + "\t" + v.getFirstParent() + "\t"
171: + v.getAllChildren().size() + "\n");
172: buf.append(v.dump());
173: }
174: System.out.println(buf);
175: }
176:
177: // ////////////////////////////////////////////////
178: // OPERATIONS
179:
180: private boolean equalHelper(Object field1, Object field2) {
181: if (field1 == null && field2 == null)
182: return true;
183: if (field1 == null && field2 != null)
184: return false;
185: if (field1 != null && field2 == null)
186: return false;
187: if (!field1.getClass().equals(field2.getClass()))
188: return false;
189: return field1.equals(field2);
190: }
191:
192: @Override
193: public boolean equals(Object other) {
194: assert this .vm.getModel().isOpen();
195:
196: try {
197: if (!(other instanceof VersionedModel)) {
198: log.debug("other is a " + other.getClass());
199: return false;
200: }
201: VersionedModel vm = (VersionedModel) other;
202: if (!equalHelper(vm.getAllBranches(), getAllBranches())) {
203: log.debug("different getAllBranches");
204: return false;
205: }
206: if (!equalHelper(vm.getAllVersions(), getAllVersions())) {
207: log.debug("different getAllVersions");
208: return false;
209: }
210: if (!equalHelper(vm.getBranches(), getBranches())) {
211: log.debug("different getBranches");
212: return false;
213: }
214: if (!equalHelper(vm.getChangeLog(), getChangeLog())) {
215: log.debug("different getChangeLog");
216: return false;
217: }
218: if (!equalHelper(vm.getComment(), getComment())) {
219: log.debug("different getComment");
220: return false;
221: }
222: if (!equalHelper(vm.getCreationTime(), getCreationTime())) {
223: log.debug("different getCreationTime");
224: return false;
225: }
226: if (!equalHelper(vm.getLabel(), getLabel())) {
227: log.debug("different getLabel");
228: return false;
229: }
230: if (!equalHelper(vm.getFirstVersion(), getFirstVersion())) {
231: log.debug("different getFirstVersion");
232: return false;
233: }
234: if (!equalHelper(vm.getLastMainbranchVersion(),
235: getLastMainbranchVersion())) {
236: log.debug("different getLastMainbranchVersion");
237: return false;
238: }
239: if (!equalHelper(vm.getLastModifiedBy(),
240: getLastModifiedBy())) {
241: log.debug("different getLastModifiedBy");
242: return false;
243: }
244: if (!equalHelper(vm.getLastVersions(), getLastVersions())) {
245: log.debug("different getLastVersions");
246: return false;
247: }
248: if (!equalHelper(vm.getLastModifiedBy(),
249: getLastModifiedBy())) {
250: log.debug("different getLastModifiedBy");
251: return false;
252: }
253: if (!equalHelper(vm.getProvenance(), getProvenance())) {
254: log.debug("different getProvenance");
255: return false;
256: }
257: if (!equalHelper(vm.getRoot(), getRoot())) {
258: log.debug("different getRoot");
259: return false;
260: }
261: // if (!vm.getStatistics().equals(getStatistics()))
262: // return false;
263: if (!equalHelper(vm.getURI(), getURI())) {
264: log.debug("different getURI");
265: return false;
266: }
267: if (!equalHelper(vm.getUserdefinedMetadata(),
268: getUserdefinedMetadata())) {
269: log.debug("different getUserdefinedMetadata");
270: return false;
271: }
272: } catch (Exception e) {
273: e.printStackTrace();
274: return false;
275: }
276: return true;
277: }
278:
279: /**
280: * @return a set of all branch labels used in the version tree.
281: */
282: public Set<String> getAllBranches() {
283: Set<String> branchLabels = new HashSet<String>();
284: List<Version> allVersions = getAllVersions();
285: for (int i = 0; i < allVersions.size(); i++) {
286: branchLabels.add(allVersions.get(i).getBranchLabel());
287: }
288: return branchLabels;
289: }
290:
291: /**
292: * @return a list of all versions in this version tree
293: */
294: public List<org.ontoware.semversion.Version> getAllVersions() {
295: org.ontoware.semversion.impl.generated.Version[] genVersions = (org.ontoware.semversion.impl.generated.Version[]) Bridge
296: .getAllValues(
297: vm.getModel(),
298: vm.getResource(),
299: org.ontoware.semversion.impl.generated.VersionedModel.VERSION,
300: org.ontoware.semversion.impl.generated.Version.class);
301: List<org.ontoware.semversion.Version> list = new ArrayList<org.ontoware.semversion.Version>();
302: for (org.ontoware.semversion.impl.generated.Version vi : genVersions) {
303: list.add(new org.ontoware.semversion.Version(vi,
304: getSession()));
305: }
306: return list;
307: }
308:
309: /**
310: * @return TODO unclear semantics
311: */
312: public List<Branch> getBranches() {
313: List<Branch> result = new ArrayList<Branch>();
314: for (Version leaf : getLastVersions()) {
315: Branch branch = new Branch();
316: addToBranch(branch, leaf);
317: result.add(branch);
318: }
319: return result;
320: }
321:
322: /**
323: * @return a list of all changes that happened in this version tree
324: */
325: public List<Change> getChangeLog() {
326:
327: List<Change> changes = new ArrayList<Change>();
328: for (Version v : getAllVersions()) {
329:
330: String changeCause = v.getChangeCause();
331: if (changeCause == null) {
332: changeCause = "unknown";
333: }
334: Change c = new Change(v, changeCause);
335: changes.add(c);
336: }
337: return changes;
338: }
339:
340: private int getChildrenCount(Version root) {
341: assert root != null;
342: int childrenCount = 0;
343: for (Version v : root.getAllChildren()) {
344: childrenCount += getChildrenCount(v);
345: }
346: return childrenCount;
347: }
348:
349: /**
350: * @return the root version, if any, or null
351: */
352: public Version getFirstVersion() {
353: try {
354: return getRoot();
355: } catch (RDFDataException e) {
356: return null;
357: }
358: }
359:
360: /**
361: * @return the most recent version of the branch "main" or null, if no main
362: * branch version exists. Root is automatically considered to be in
363: * the "main" branch.
364: */
365: public Version getLastMainbranchVersion() {
366: return getLastVersionOfBranch(SemVersion.MAIN_BRANCH);
367: }
368:
369: /**
370: * @return User who made the last modifications to this versioned model or
371: * null if no versions are in the versioned model
372: */
373: public String getLastModifiedBy() {
374: if (getMostRecentVersion() == null)
375: return null;
376: else
377: return getMostRecentVersion().getUser().getName();
378: }
379:
380: /**
381: * @return the most recent version of the branch 'branchLabel' or null
382: */
383: public Version getLastVersionOfBranch(String branchLabel) {
384: for (Version v : getAllVersions()) {
385: String brLabel = v.getBranchLabel();
386: if (brLabel != null && brLabel.equals(branchLabel)
387: && !v.hasChildWithSameBranchLabel())
388: return v;
389: }
390: return null;
391: }
392:
393: /**
394: * @return all versions that have no children = all leaves of the version
395: * tree
396: */
397: public List<Version> getLastVersions() {
398: List<Version> allVersions = new ArrayList<Version>();
399: for (Version v : getAllVersions()) {
400: if (v.getAllChildren().size() == 0)
401: allVersions.add(v);
402: }
403: return allVersions;
404: }
405:
406: /**
407: * @return a List of all users that are authors of a leaf version
408: */
409: public List<User> getListLastModifiedBy() {
410: List<User> result = new ArrayList<User>();
411: for (Version v : getLastVersions())
412: result.add(v.getUser());
413: return result;
414: }
415:
416: /**
417: * @return the most recent version of the version tree
418: */
419: private Version getMostRecentVersion() {
420: try {
421: // for each Version in VersionedModel
422: Calendar mostRecent = Calendar.getInstance();
423: mostRecent.setTime(new Date(Long.MIN_VALUE));
424: Version mostRecentVersion = null;
425: for (Version v : getAllVersions()) {
426: Calendar d = v.getCreationTime();
427: if (d.after(mostRecent)) {
428: mostRecent = d;
429: mostRecentVersion = v;
430: }
431: }
432: return mostRecentVersion;
433: } catch (RDFDataException e) {
434: throw new RuntimeException(e);
435: }
436: }
437:
438: protected org.ontoware.semversion.impl.generated.VersionedModel getReactorVersionedModel() {
439: return this .vm;
440: }
441:
442: /**
443: * @return the root version of the version tree or null, if none has been
444: * set
445: */
446: public Version getRoot() throws RDFDataException {
447: org.ontoware.semversion.impl.generated.Version rootVersion = this .vm
448: .getRoot();
449: if (rootVersion == null)
450: return null;
451: else
452: return new Version(rootVersion, getSession());
453: }
454:
455: /**
456: * @return a Calendar set to the time when has the latest version of this
457: * versionedmodel been modified
458: */
459: public Calendar getTimestampLastModified() {
460: // TODO a faster impl via SPARQL might be possible
461: Version recent = getMostRecentVersion();
462: return recent.getCreationTime();
463: }
464:
465: /**
466: * Get a particular version from versionedmodel without having to iterate
467: * through all of the versions
468: *
469: * @return the version with the given URI if it exists, otherwise null
470: */
471: public Version getVersion(URI versionURI) {
472: if (org.ontoware.semversion.impl.generated.Version.hasInstance(
473: vm.getModel(), versionURI)) {
474: return new Version(vm.getModel(), getSession(), versionURI,
475: false);
476: } else
477: return null;
478: }
479:
480: /**
481: * @return the number of different versions in the version tree
482: */
483: public int getVersionCount() {
484: Version root;
485: try {
486: root = getRoot();
487: if (root == null) {
488: log.debug("no root, no versions");
489: return 0;
490: }
491: // recursive
492: else
493: return getChildrenCount(root) + 1;
494: } catch (RDFDataException e) {
495: throw new RuntimeException(e);
496: }
497: }
498:
499: /**
500: * @return all versions in a list
501: */
502: public List<Version> getVersions() {
503: List<Version> vis = new ArrayList<Version>();
504: for (Version vi : getAllVersions()) {
505: vis.add(vi);
506: }
507: return vis;
508: }
509:
510: /**
511: *
512: * @param start
513: * earliest creation date
514: * @param end
515: * latest creation date
516: * @param user
517: * @return the list of Versions created between start and end by user user
518: * @throws RDFDataException
519: */
520: public List<Version> queryForVersions(Calendar start, Calendar end,
521: User user) throws RDFDataException {
522: List<Version> vis = new ArrayList<Version>();
523: for (Version vi : getAllVersions()) {
524: if (vi.getCreationTime().compareTo(start) >= 0
525: && vi.getCreationTime().compareTo(end) <= 0
526: && vi.getUser().equals(user))
527: vis.add(vi);
528: }
529: return vis;
530: }
531:
532: /**
533: * removes all values and sets this one, used for testing only
534: */
535: protected void setRoot(Version value) throws RDFDataException {
536: assert value != null;
537: vm.setRoot(value.getReactorVersion());
538: }
539: }
|