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; } }