blob: 59013e147941d1a3e0c2f8708ce4a64d2e7f35a3 [file] [log] [blame]
package org.apache.taverna.scufl2.rdfxml;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.io.InputStream;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.taverna.scufl2.api.annotation.Revision;
import org.apache.taverna.scufl2.api.io.ReaderException;
import org.apache.taverna.scufl2.xml.roevo.Change;
import org.apache.taverna.scufl2.xml.roevo.ChangeSpecification;
import org.apache.taverna.scufl2.xml.roevo.ChangeSpecification.HasChange;
import org.apache.taverna.scufl2.xml.roevo.RoEvoDocument;
import org.apache.taverna.scufl2.xml.roevo.VersionableResource;
import org.apache.taverna.scufl2.xml.rdf.Resource;
public class RevisionParser {
private JAXBContext jaxbContext;
protected JAXBContext getJaxbContext() throws JAXBException {
if (jaxbContext == null) {
Class<?>[] packages = {
org.apache.taverna.scufl2.xml.roevo.ObjectFactory.class,
org.apache.taverna.scufl2.xml.prov.ObjectFactory.class,
org.apache.taverna.scufl2.xml.rdf.ObjectFactory.class,
org.apache.taverna.scufl2.xml.rdfs.ObjectFactory.class };
jaxbContext = JAXBContext.newInstance(packages);
}
return jaxbContext;
}
@SuppressWarnings({ "unchecked" })
public Map<URI, Revision> readRevisionChain(
InputStream revisionDocumentStream, URI base)
throws ReaderException {
JAXBElement<RoEvoDocument> roEvoDoc;
try {
Unmarshaller unmarshaller = getJaxbContext().createUnmarshaller();
roEvoDoc = (JAXBElement<RoEvoDocument>) unmarshaller
.unmarshal(revisionDocumentStream);
} catch (JAXBException e) {
throw new ReaderException(e);
}
RoEvoDocument document = roEvoDoc.getValue();
if (document.getBase() != null)
base = base.resolve(document.getBase());
Map<URI, Revision> revisions = new LinkedHashMap<>();
// NOTE: Silly hack to iterate/cast in one go.. will it work?
for (VersionableResource verResource : document.getAny().toArray(
new VersionableResource[0]))
parse(base, verResource, revisions);
return revisions;
}
private Revision parse(URI base, VersionableResource verResource,
Map<URI, Revision> revisions) throws ReaderException {
URI uri = base.resolve(verResource.getAbout());
Revision revision = addOrExisting(uri, revisions);
if (verResource.getGeneratedAtTime() != null) {
XMLGregorianCalendar xmlCal = verResource.getGeneratedAtTime()
.getValue();
revision.setGeneratedAtTime(xmlCal.toGregorianCalendar());
}
Resource wasRevisionOf = verResource.getWasRevisionOf();
if (wasRevisionOf != null) {
// TODO Put these in a map
Revision r = addOrExisting(
base.resolve(wasRevisionOf.getResource()), revisions);
revision.setPreviousRevision(r);
}
if (verResource.getWasChangedBy() != null) {
ChangeSpecification changeSpec = verResource.getWasChangedBy()
.getChangeSpecification();
if (changeSpec.getFromVersion() != null) {
Revision r = addOrExisting(
base.resolve(changeSpec.getFromVersion().getResource()),
revisions);
if (revision.getPreviousRevision() != null
&& revision.getPreviousRevision() != r)
throw new ReaderException(
"Inconsistent previous revision: "
+ revision.getPreviousRevision()
.getIdentifier() + " or "
+ r.getIdentifier());
revision.setPreviousRevision(r);
}
if (changeSpec.getType() != null)
revision.setChangeSpecificationType(base.resolve(changeSpec
.getType().getResource()));
for (HasChange hasChange : changeSpec.getHasChange()) {
if (hasChange.getAddition() != null) {
Set<URI> additions = parse(hasChange.getAddition(), base);
// Note: Use addAll in case a buggy XML has multiple
// <hasChange><Addition>
revision.getAdditionOf().addAll(additions);
}
if (hasChange.getModification() != null) {
Set<URI> modifications = parse(hasChange.getModification(),
base);
revision.getModificationsOf().addAll(modifications);
}
if (hasChange.getRemoval() != null) {
Set<URI> removals = parse(hasChange.getRemoval(), base);
revision.getRemovalOf().addAll(removals);
}
}
}
for (Resource assoc : verResource.getWasAttributedTo())
revision.getWasAttributedTo()
.add(base.resolve(assoc.getResource()));
for (Resource assoc : verResource.getHadOriginalSource()) {
Revision r = addOrExisting(base.resolve(assoc.getResource()),
revisions);
revision.getHadOriginalSources().add(r);
}
return revision;
}
private Revision addOrExisting(URI uri, Map<URI, Revision> revisions) {
Revision rev = revisions.get(uri);
if (rev != null)
return rev;
rev = new Revision(uri, null);
revisions.put(uri, rev);
return rev;
}
private Set<URI> parse(Change addition, URI base) {
Set<URI> uris = new LinkedHashSet<>();
for (Resource r : addition.getRelatedResource())
uris.add(base.resolve(r.getResource()));
return uris;
}
}