/* * Copyright 2012 JBoss Inc * * Licensed 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. */ package org.artificer.atom.visitors; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang.StringUtils; import org.artificer.atom.ArtificerAtomConstants; import org.artificer.atom.ArtificerAtomUtils; import org.artificer.common.ArtifactType; import org.artificer.common.ArtificerConstants; import org.artificer.common.ArtificerModelUtils; import org.artificer.common.MediaType; import org.artificer.common.visitors.ArtifactVisitorHelper; import org.artificer.common.visitors.HierarchicalArtifactVisitor; import org.jboss.resteasy.plugins.providers.atom.Category; import org.jboss.resteasy.plugins.providers.atom.Content; import org.jboss.resteasy.plugins.providers.atom.Entry; import org.jboss.resteasy.plugins.providers.atom.Link; import org.jboss.resteasy.plugins.providers.atom.Person; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Artifact; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.DocumentArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtendedArtifactType; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtendedDocument; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Property; import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XmlDocument; import java.lang.reflect.Method; import java.net.URI; import java.util.Set; /** * Visitor used to convert an artifact to an Atom entry. * * @author eric.wittmann@redhat.com */ public class ArtifactToSummaryAtomEntryVisitor extends HierarchicalArtifactVisitor { protected String baseUrl = ""; protected Entry atomEntry; protected Exception failure; protected Set<String> propertyNames; private String atomLink; private String mediaLink; /** * Constructor. * @param baseUrl */ public ArtifactToSummaryAtomEntryVisitor(String baseUrl) { this.baseUrl = baseUrl; } /** * Constructor. * @param baseUrl * @param propNames */ public ArtifactToSummaryAtomEntryVisitor(String baseUrl, Set<String> propNames) { this.baseUrl = baseUrl; this.propertyNames = propNames; } /** * Called to reset the created entry and failure {@link Exception}. Call this * between visits of different artifacts - useful if you want to re-use the * visitor in a loop. */ public void reset() { this.atomEntry = null; this.failure = null; } /** * @return the atomEntry */ public Entry getAtomEntry() throws Exception { if (this.failure != null) throw this.failure; return atomEntry; } /** * Sets the Atom entry. * @param entry an Atom {@link Entry} */ protected void setAtomEntry(Entry entry) { this.atomEntry = entry; } /** * Creates the base Atom Entry, doing the stuff that's common to all types of artifacts. * @see org.artificer.common.visitors.AbstractArtifactVisitor#visitBase(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType) */ @SuppressWarnings("unchecked") @Override protected void visitBase(BaseArtifactType artifact) { try { ArtifactType artifactType = ArtifactType.valueOf(artifact); Entry entry = new Entry(); if (artifact.getUuid() != null) entry.setId(new URI("urn:uuid:" + artifact.getUuid())); if (artifact.getLastModifiedTimestamp() != null) entry.setUpdated(artifact.getLastModifiedTimestamp().toGregorianCalendar().getTime()); if (artifact.getName() != null) entry.setTitle(artifact.getName()); if (artifact.getCreatedTimestamp() != null) entry.setPublished(artifact.getCreatedTimestamp().toGregorianCalendar().getTime()); if (artifact.getCreatedBy() != null) entry.getAuthors().add(new Person(artifact.getCreatedBy())); if (artifact.getDescription() != null) entry.setSummary(artifact.getDescription()); entry.getExtensionAttributes().put(ArtificerConstants.SRAMP_DERIVED_QNAME, String.valueOf(artifactType.isDerived())); String archiveUuid = artifact.getOtherAttributes().get(ArtificerConstants.ARTIFICER_EXPANDED_FROM_ARCHIVE_UUID_QNAME); entry.getExtensionAttributes().put(ArtificerConstants.ARTIFICER_EXPANDED_FROM_ARCHIVE_QNAME, String.valueOf(StringUtils.isNotBlank(archiveUuid))); atomLink = baseUrl + "/s-ramp/" + artifactType.getModel() + "/" + artifactType.getType() + "/" + artifact.getUuid(); mediaLink = atomLink + "/media"; // Self can be accessed at /s-ramp/{model}/{artifact-type}/{uid} Link linkToSelf = new Link(); linkToSelf.setType(MediaType.APPLICATION_ATOM_XML_ENTRY_TYPE); linkToSelf.setRel("self"); linkToSelf.setHref(new URI(atomLink)); entry.getLinks().add(linkToSelf); // Link to edit-media can be accessed at /s-ramp/{model}/{artifact-type}/{uid}/edit-media Link linkToEditMedia = new Link(); linkToEditMedia.setType(MediaType.APPLICATION_ATOM_XML_ENTRY_TYPE); linkToEditMedia.setRel("edit-media"); linkToEditMedia.setHref(new URI(mediaLink)); entry.getLinks().add(linkToEditMedia); // Link to edit can be accessed at /s-ramp/{model}/{artifact-type}/{uid} Link linkToEdit = new Link(); linkToEdit.setType(MediaType.APPLICATION_ATOM_XML_ENTRY_TYPE); linkToEdit.setRel("edit"); linkToEdit.setHref(new URI(atomLink)); entry.getLinks().add(linkToEdit); // Type category Category typeCat = new Category(); typeCat.setTerm(artifactType.getType()); typeCat.setLabel(artifactType.getLabel()); typeCat.setScheme(ArtificerAtomConstants.X_S_RAMP_TYPE_URN); entry.getCategories().add(typeCat); // Kind category Category kindCat = new Category(); if (artifactType.isDerived()) { kindCat.setTerm("derived"); kindCat.setLabel("Derived S-RAMP Artifact"); } else { kindCat.setTerm("modeled"); kindCat.setLabel("Modeled S-RAMP Artifact"); } kindCat.setScheme(ArtificerAtomConstants.X_S_RAMP_KIND_URN); entry.getCategories().add(kindCat); // Model category Category modelCat = new Category(); modelCat.setTerm(artifactType.getModel()); modelCat.setLabel(artifactType.getLabel()); modelCat.setScheme(ArtificerAtomConstants.X_S_RAMP_MODEL_URN); entry.getCategories().add(modelCat); setAtomEntry(entry); if (includeArtifact()) { Artifact artifactWrapper = new Artifact(); BaseArtifactType includedArtifact = createIncludedArtifact(artifact); Method method = Artifact.class.getMethod("set" + includedArtifact.getClass().getSimpleName(), includedArtifact.getClass()); method.invoke(artifactWrapper, includedArtifact); entry.setAnyOtherJAXBObject(artifactWrapper); } } catch (Exception e) { this.failure = e; } } @Override protected void visitDocument(DocumentArtifactType artifact) { super.visitDocument(artifact); try { if (this.atomEntry != null) { // Original content can be accessed at /s-ramp/{model}/{artifact-type}/{uid}/media ArtifactContentTypeVisitor ctVisitor = new ArtifactContentTypeVisitor(); ArtifactVisitorHelper.visitArtifact(ctVisitor, artifact); Content content = new Content(); content.setType(ctVisitor.getContentType()); content.setSrc(new URI(mediaLink)); atomEntry.setContent(content); // Alternate can be accessed at /s-ramp/{model}/{artifact-type}/{uid}/media // Only for Document style artifacts. Link linkToAlternate = new Link(); linkToAlternate.setType(ctVisitor.getContentType()); linkToAlternate.setRel("alternate"); linkToAlternate.setHref(new URI(mediaLink)); atomEntry.getLinks().add(linkToAlternate); } } catch (Exception e) { this.failure = e; } } @Override public void visit(XmlDocument artifact) { super.visit(artifact); visitDocument(artifact); try { if (this.atomEntry != null) { ArtificerAtomUtils.setXmlContentType(artifact, atomLink, atomEntry); } } catch (Exception e) { this.failure = e; } } /** * @see org.artificer.common.visitors.AbstractArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtendedArtifactType) */ @SuppressWarnings("unchecked") @Override public void visit(ExtendedArtifactType artifact) { super.visit(artifact); if (this.atomEntry != null) { String extendedType = artifact.getExtendedType(); this.atomEntry.getExtensionAttributes().put(ArtificerConstants.SRAMP_EXTENDED_TYPE_QNAME, extendedType); } } /** * @see org.artificer.common.visitors.ArtifactVisitor#visit(org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ExtendedDocument) */ @SuppressWarnings("unchecked") @Override public void visit(ExtendedDocument artifact) { super.visit(artifact); if (this.atomEntry != null) { String extendedType = artifact.getExtendedType(); this.atomEntry.getExtensionAttributes().put(ArtificerConstants.SRAMP_EXTENDED_TYPE_QNAME, extendedType); } } /** * Returns true if we should include the Artifact wrapper in the Entry. For the summary * {@link Entry} we would include the artifact wrapper only if we're returning some * additional custom properties. */ protected boolean includeArtifact() { return propertyNames != null && propertyNames.size() > 0; } /** * Creates the artifact that should be included in the returned Entry. * @throws IllegalAccessException * @throws InstantiationException */ protected BaseArtifactType createIncludedArtifact(BaseArtifactType artifact) throws InstantiationException, IllegalAccessException { if (includeArtifact()) { BaseArtifactType includedArtifact = artifact.getClass().newInstance(); for (String propertyName : propertyNames) { for (Property customProperty : artifact.getProperty()) { // Custom property? if (propertyName.equalsIgnoreCase(customProperty.getPropertyName())) { ArtificerModelUtils.setCustomProperty(includedArtifact, customProperty.getPropertyName(), customProperty.getPropertyValue()); break; } // Otherwise, we need to use reflection to check other built-in properties. Simplify with BeanUtils try { BeanUtils.setProperty(includedArtifact, propertyName, BeanUtils.getProperty(artifact, propertyName)); } catch (Exception e) { // Eat it, with contempt } } } return includedArtifact; } else { return null; } } }