blob: 63528463cd60572d0c94d30e3e44fcffd0fb1388 [file] [log] [blame]
/*
* 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.
*/
package org.apache.nifi.registry.service.extension.docs;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.extension.bundle.BundleInfo;
import org.apache.nifi.registry.extension.component.ExtensionMetadata;
import org.apache.nifi.registry.extension.component.manifest.AllowableValue;
import org.apache.nifi.registry.extension.component.manifest.ControllerServiceDefinition;
import org.apache.nifi.registry.extension.component.manifest.DeprecationNotice;
import org.apache.nifi.registry.extension.component.manifest.DynamicProperty;
import org.apache.nifi.registry.extension.component.manifest.ExpressionLanguageScope;
import org.apache.nifi.registry.extension.component.manifest.Extension;
import org.apache.nifi.registry.extension.component.manifest.InputRequirement;
import org.apache.nifi.registry.extension.component.manifest.Property;
import org.apache.nifi.registry.extension.component.manifest.ProvidedServiceAPI;
import org.apache.nifi.registry.extension.component.manifest.Restricted;
import org.apache.nifi.registry.extension.component.manifest.Restriction;
import org.apache.nifi.registry.extension.component.manifest.Stateful;
import org.apache.nifi.registry.extension.component.manifest.SystemResourceConsideration;
import org.springframework.stereotype.Service;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.nifi.registry.service.extension.docs.DocumentationConstants.CSS_PATH;
@Service
public class HtmlExtensionDocWriter implements ExtensionDocWriter {
@Override
public void write(final ExtensionMetadata extensionMetadata, final Extension extension, final OutputStream outputStream) throws IOException {
try {
final XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, "UTF-8");
xmlStreamWriter.writeDTD("<!DOCTYPE html>");
xmlStreamWriter.writeStartElement("html");
xmlStreamWriter.writeAttribute("lang", "en");
writeHead(extensionMetadata, xmlStreamWriter);
writeBody(extensionMetadata, extension, xmlStreamWriter);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.close();
outputStream.flush();
} catch (XMLStreamException | FactoryConfigurationError e) {
throw new IOException("Unable to create XMLOutputStream", e);
}
}
private void writeHead(final ExtensionMetadata extensionMetadata, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
xmlStreamWriter.writeStartElement("head");
xmlStreamWriter.writeStartElement("meta");
xmlStreamWriter.writeAttribute("charset", "utf-8");
xmlStreamWriter.writeEndElement();
writeSimpleElement(xmlStreamWriter, "title", extensionMetadata.getDisplayName());
final String componentUsageCss = CSS_PATH + "component-usage.css";
xmlStreamWriter.writeStartElement("link");
xmlStreamWriter.writeAttribute("rel", "stylesheet");
xmlStreamWriter.writeAttribute("href", componentUsageCss);
xmlStreamWriter.writeAttribute("type", "text/css");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("script");
xmlStreamWriter.writeAttribute("type", "text/javascript");
xmlStreamWriter.writeCharacters("window.onload = function(){if(self==top) { " +
"document.getElementById('nameHeader').style.display = \"inherit\"; } }" );
xmlStreamWriter.writeEndElement();
}
private void writeBody(final ExtensionMetadata extensionMetadata, final Extension extension,
final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
xmlStreamWriter.writeStartElement("body");
writeHeader(extensionMetadata, extension, xmlStreamWriter);
writeBundleInfo(extensionMetadata, xmlStreamWriter);
writeDeprecationWarning(extension, xmlStreamWriter);
writeDescription(extensionMetadata, extension, xmlStreamWriter);
writeTags(extension, xmlStreamWriter);
writeProperties(extension, xmlStreamWriter);
writeDynamicProperties(extension, xmlStreamWriter);
writeAdditionalBodyInfo(extension, xmlStreamWriter);
writeStatefulInfo(extension, xmlStreamWriter);
writeRestrictedInfo(extension, xmlStreamWriter);
writeInputRequirementInfo(extension, xmlStreamWriter);
writeSystemResourceConsiderationInfo(extension, xmlStreamWriter);
writeProvidedServiceApis(extension, xmlStreamWriter);
writeSeeAlso(extension, xmlStreamWriter);
// end body
xmlStreamWriter.writeEndElement();
}
/**
* This method may be overridden by sub classes to write additional
* information to the body of the documentation.
*
* @param extension the component to describe
* @param xmlStreamWriter the stream writer
* @throws XMLStreamException thrown if there was a problem writing to the XML stream
*/
protected void writeAdditionalBodyInfo(final Extension extension, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
}
private void writeHeader(final ExtensionMetadata extensionMetadata, final Extension extension,
final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
xmlStreamWriter.writeStartElement("h1");
xmlStreamWriter.writeAttribute("id", "nameHeader");
xmlStreamWriter.writeAttribute("style", "display: none;");
xmlStreamWriter.writeCharacters(extensionMetadata.getDisplayName());
xmlStreamWriter.writeEndElement();
}
private void writeBundleInfoString(final ExtensionMetadata extensionMetadata, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final BundleInfo bundleInfo = extensionMetadata.getBundleInfo();
final String bundleInfoText = bundleInfo.getGroupId() + "-" + bundleInfo.getArtifactId() + "-" + bundleInfo.getVersion();
xmlStreamWriter.writeStartElement("p");
xmlStreamWriter.writeStartElement("i");
xmlStreamWriter.writeCharacters(bundleInfoText);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
}
private void writeBundleInfo(final ExtensionMetadata extensionMetadata, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final BundleInfo bundleInfo = extensionMetadata.getBundleInfo();
final String extenstionType;
switch (extensionMetadata.getType()) {
case PROCESSOR:
extenstionType = "Processor";
break;
case CONTROLLER_SERVICE:
extenstionType = "Controller Service";
break;
case REPORTING_TASK:
extenstionType = "Reporting Task";
break;
default:
throw new IllegalArgumentException("Unknown extension type: " + extensionMetadata.getType());
}
xmlStreamWriter.writeStartElement("table");
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Extension Info");
writeSimpleElement(xmlStreamWriter, "th", "Value");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "Full Name", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", extensionMetadata.getName());
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "Type", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", extenstionType);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "Bundle Group", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", bundleInfo.getGroupId());
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "Bundle Artifact", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", bundleInfo.getArtifactId());
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "Bundle Version", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", bundleInfo.getVersion());
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "Bundle Type", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", bundleInfo.getBundleType().toString());
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", "System API Version", true, "bundle-info");
writeSimpleElement(xmlStreamWriter, "td", bundleInfo.getSystemApiVersion());
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement(); // end table
}
private void writeDeprecationWarning(final Extension extension, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final DeprecationNotice deprecationNotice = extension.getDeprecationNotice();
if (deprecationNotice != null) {
xmlStreamWriter.writeStartElement("h2");
xmlStreamWriter.writeCharacters("Deprecation notice: ");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("p");
xmlStreamWriter.writeCharacters("");
if (!StringUtils.isEmpty(deprecationNotice.getReason())) {
xmlStreamWriter.writeCharacters(deprecationNotice.getReason());
} else {
xmlStreamWriter.writeCharacters("Please be aware this processor is deprecated and may be removed in the near future.");
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("p");
xmlStreamWriter.writeCharacters("Please consider using one the following alternatives: ");
final List<String> alternatives = deprecationNotice.getAlternatives();
if (alternatives != null && alternatives.size() > 0) {
xmlStreamWriter.writeStartElement("ul");
for (final String alternative : alternatives) {
xmlStreamWriter.writeStartElement("li");
xmlStreamWriter.writeCharacters(alternative);
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
} else {
xmlStreamWriter.writeCharacters("No alternative components suggested.");
}
xmlStreamWriter.writeEndElement();
}
}
private void writeDescription(final ExtensionMetadata extensionMetadata, final Extension extension, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
final String description = StringUtils.isBlank(extension.getDescription())
? "No description provided." : extension.getDescription();
writeSimpleElement(xmlStreamWriter, "h2", "Description: ");
writeSimpleElement(xmlStreamWriter, "p", description);
if (extensionMetadata.getHasAdditionalDetails()) {
xmlStreamWriter.writeStartElement("p");
final BundleInfo bundleInfo = extensionMetadata.getBundleInfo();
final String bucketName = bundleInfo.getBucketName();
final String groupId = bundleInfo.getGroupId();
final String artifactId = bundleInfo.getArtifactId();
final String version = bundleInfo.getVersion();
final String extensionName = extensionMetadata.getName();
final String additionalDetailsPath = "/nifi-registry-api/extension-repository/"
+ bucketName + "/" + groupId + "/" + artifactId + "/" + version
+ "/extensions/" + extensionName + "/docs/additional-details";
writeLink(xmlStreamWriter, "Additional Details...", additionalDetailsPath);
xmlStreamWriter.writeEndElement();
}
}
private void writeTags(final Extension extension, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final List<String> tags = extension.getTags();
xmlStreamWriter.writeStartElement("h3");
xmlStreamWriter.writeCharacters("Tags: ");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("p");
if (tags != null) {
final String tagString = StringUtils.join(tags, ", ");
xmlStreamWriter.writeCharacters(tagString);
} else {
xmlStreamWriter.writeCharacters("No tags provided.");
}
xmlStreamWriter.writeEndElement();
}
protected void writeProperties(final Extension extension, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final List<Property> properties = extension.getProperties();
writeSimpleElement(xmlStreamWriter, "h3", "Properties: ");
if (properties != null && properties.size() > 0) {
final boolean containsExpressionLanguage = containsExpressionLanguage(extension);
final boolean containsSensitiveProperties = containsSensitiveProperties(extension);
xmlStreamWriter.writeStartElement("p");
xmlStreamWriter.writeCharacters("In the list below, the names of required properties appear in ");
writeSimpleElement(xmlStreamWriter, "strong", "bold");
xmlStreamWriter.writeCharacters(". Any other properties (not in bold) are considered optional. " +
"The table also indicates any default values");
if (containsExpressionLanguage) {
if (!containsSensitiveProperties) {
xmlStreamWriter.writeCharacters(", and ");
} else {
xmlStreamWriter.writeCharacters(", ");
}
xmlStreamWriter.writeCharacters("whether a property supports the NiFi Expression Language");
}
if (containsSensitiveProperties) {
xmlStreamWriter.writeCharacters(", and whether a property is considered " + "\"sensitive\", meaning that its value will be encrypted");
}
xmlStreamWriter.writeCharacters(".");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("table");
xmlStreamWriter.writeAttribute("id", "properties");
// write the header row
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Name");
writeSimpleElement(xmlStreamWriter, "th", "Default Value");
writeSimpleElement(xmlStreamWriter, "th", "Allowable Values");
writeSimpleElement(xmlStreamWriter, "th", "Description");
xmlStreamWriter.writeEndElement();
// write the individual properties
for (Property property : properties) {
xmlStreamWriter.writeStartElement("tr");
xmlStreamWriter.writeStartElement("td");
xmlStreamWriter.writeAttribute("id", "name");
if (property.isRequired()) {
writeSimpleElement(xmlStreamWriter, "strong", property.getDisplayName());
} else {
xmlStreamWriter.writeCharacters(property.getDisplayName());
}
xmlStreamWriter.writeEndElement();
writeSimpleElement(xmlStreamWriter, "td", property.getDefaultValue(), false, "default-value");
xmlStreamWriter.writeStartElement("td");
xmlStreamWriter.writeAttribute("id", "allowable-values");
writeValidValues(xmlStreamWriter, property);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("td");
xmlStreamWriter.writeAttribute("id", "description");
if (property.getDescription() != null && property.getDescription().trim().length() > 0) {
xmlStreamWriter.writeCharacters(property.getDescription());
} else {
xmlStreamWriter.writeCharacters("No Description Provided.");
}
if (property.isSensitive()) {
xmlStreamWriter.writeEmptyElement("br");
writeSimpleElement(xmlStreamWriter, "strong", "Sensitive Property: true");
}
if (property.isExpressionLanguageSupported()) {
xmlStreamWriter.writeEmptyElement("br");
String text = "Supports Expression Language: true";
final String perFF = " (will be evaluated using flow file attributes and variable registry)";
final String registry = " (will be evaluated using variable registry only)";
final InputRequirement inputRequirement = extension.getInputRequirement();
switch(property.getExpressionLanguageScope()) {
case FLOWFILE_ATTRIBUTES:
if(inputRequirement != null && inputRequirement.equals(InputRequirement.INPUT_FORBIDDEN)) {
text += registry;
} else {
text += perFF;
}
break;
case VARIABLE_REGISTRY:
text += registry;
break;
case NONE:
default:
// in case legacy/deprecated method has been used to specify EL support
text += " (undefined scope)";
break;
}
writeSimpleElement(xmlStreamWriter, "strong", text);
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
} else {
writeSimpleElement(xmlStreamWriter, "p", "This component has no required or optional properties.");
}
}
private boolean containsExpressionLanguage(final Extension extension) {
for (Property property : extension.getProperties()) {
if (property.isExpressionLanguageSupported()) {
return true;
}
}
return false;
}
private boolean containsSensitiveProperties(final Extension extension) {
for (Property property : extension.getProperties()) {
if (property.isSensitive()) {
return true;
}
}
return false;
}
protected void writeValidValues(final XMLStreamWriter xmlStreamWriter, final Property property) throws XMLStreamException {
if (property.getAllowableValues() != null && property.getAllowableValues().size() > 0) {
xmlStreamWriter.writeStartElement("ul");
for (AllowableValue value : property.getAllowableValues()) {
xmlStreamWriter.writeStartElement("li");
xmlStreamWriter.writeCharacters(value.getDisplayName());
if (!StringUtils.isBlank(value.getDescription())) {
writeValidValueDescription(xmlStreamWriter, value.getDescription());
}
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
} else if (property.getControllerServiceDefinition() != null) {
final ControllerServiceDefinition serviceDefinition = property.getControllerServiceDefinition();
final String controllerServiceClass = getSimpleName(serviceDefinition.getClassName());
final String group = serviceDefinition.getGroupId() == null ? "unknown" : serviceDefinition.getGroupId();
final String artifact = serviceDefinition.getArtifactId() == null ? "unknown" : serviceDefinition.getArtifactId();
final String version = serviceDefinition.getVersion() == null ? "unknown" : serviceDefinition.getVersion();
writeSimpleElement(xmlStreamWriter, "strong", "Controller Service API: ");
xmlStreamWriter.writeEmptyElement("br");
xmlStreamWriter.writeCharacters(controllerServiceClass);
writeValidValueDescription(xmlStreamWriter, group + "-" + artifact + "-" + version);
// xmlStreamWriter.writeEmptyElement("br");
// xmlStreamWriter.writeCharacters(group);
// xmlStreamWriter.writeEmptyElement("br");
// xmlStreamWriter.writeCharacters(artifact);
// xmlStreamWriter.writeEmptyElement("br");
// xmlStreamWriter.writeCharacters(version);
}
}
private String getSimpleName(final String extensionName) {
int index = extensionName.lastIndexOf('.');
if (index > 0 && (index < (extensionName.length() - 1))) {
return extensionName.substring(index + 1);
} else {
return extensionName;
}
}
private void writeValidValueDescription(final XMLStreamWriter xmlStreamWriter, final String description) throws XMLStreamException {
xmlStreamWriter.writeCharacters(" ");
xmlStreamWriter.writeStartElement("img");
xmlStreamWriter.writeAttribute("src", "/nifi-registry-docs/images/iconInfo.png");
xmlStreamWriter.writeAttribute("alt", description);
xmlStreamWriter.writeAttribute("title", description);
xmlStreamWriter.writeEndElement();
}
private void writeDynamicProperties(final Extension extension, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final List<DynamicProperty> dynamicProperties = extension.getDynamicProperties();
if (dynamicProperties != null && dynamicProperties.size() > 0) {
writeSimpleElement(xmlStreamWriter, "h3", "Dynamic Properties: ");
xmlStreamWriter.writeStartElement("p");
xmlStreamWriter.writeCharacters("Dynamic Properties allow the user to specify both the name and value of a property.");
xmlStreamWriter.writeStartElement("table");
xmlStreamWriter.writeAttribute("id", "dynamic-properties");
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Name");
writeSimpleElement(xmlStreamWriter, "th", "Value");
writeSimpleElement(xmlStreamWriter, "th", "Description");
xmlStreamWriter.writeEndElement();
for (final DynamicProperty dynamicProperty : dynamicProperties) {
final String name = StringUtils.isBlank(dynamicProperty.getName()) ? "Not Specified" : dynamicProperty.getName();
final String value = StringUtils.isBlank(dynamicProperty.getValue()) ? "Not Specified" : dynamicProperty.getValue();
final String description = StringUtils.isBlank(dynamicProperty.getDescription()) ? "Not Specified" : dynamicProperty.getDescription();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", name, false, "name");
writeSimpleElement(xmlStreamWriter, "td", value, false, "value");
xmlStreamWriter.writeStartElement("td");
xmlStreamWriter.writeCharacters(description);
xmlStreamWriter.writeEmptyElement("br");
final ExpressionLanguageScope elScope = dynamicProperty.getExpressionLanguageScope() == null
? ExpressionLanguageScope.NONE : dynamicProperty.getExpressionLanguageScope();
String text;
if(elScope.equals(ExpressionLanguageScope.NONE)) {
if(dynamicProperty.isExpressionLanguageSupported()) {
text = "Supports Expression Language: true (undefined scope)";
} else {
text = "Supports Expression Language: false";
}
} else {
switch(elScope) {
case FLOWFILE_ATTRIBUTES:
text = "Supports Expression Language: true (will be evaluated using flow file attributes and variable registry)";
break;
case VARIABLE_REGISTRY:
text = "Supports Expression Language: true (will be evaluated using variable registry only)";
break;
case NONE:
default:
text = "Supports Expression Language: false";
break;
}
}
writeSimpleElement(xmlStreamWriter, "strong", text);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
}
}
private void writeStatefulInfo(final Extension extension, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
final Stateful stateful = extension.getStateful();
writeSimpleElement(xmlStreamWriter, "h3", "State management: ");
if(stateful != null) {
final List<String> scopes = Optional.ofNullable(stateful.getScopes())
.map(List::stream)
.orElseGet(Stream::empty)
.map(s -> s.toString())
.collect(Collectors.toList());
final String description = StringUtils.isBlank(stateful.getDescription()) ? "Not Specified" : stateful.getDescription();
xmlStreamWriter.writeStartElement("table");
xmlStreamWriter.writeAttribute("id", "stateful");
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Scope");
writeSimpleElement(xmlStreamWriter, "th", "Description");
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", StringUtils.join(scopes, ", "));
writeSimpleElement(xmlStreamWriter, "td", description);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
} else {
xmlStreamWriter.writeCharacters("This component does not store state.");
}
}
private void writeRestrictedInfo(final Extension extension, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
final Restricted restricted = extension.getRestricted();
writeSimpleElement(xmlStreamWriter, "h3", "Restricted: ");
if(restricted != null) {
final String generalRestrictionExplanation = restricted.getGeneralRestrictionExplanation();
if (!StringUtils.isBlank(generalRestrictionExplanation)) {
xmlStreamWriter.writeCharacters(generalRestrictionExplanation);
}
final List<Restriction> restrictions = restricted.getRestrictions();
if (restrictions != null && restrictions.size() > 0) {
xmlStreamWriter.writeStartElement("table");
xmlStreamWriter.writeAttribute("id", "restrictions");
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Required Permission");
writeSimpleElement(xmlStreamWriter, "th", "Explanation");
xmlStreamWriter.writeEndElement();
for (Restriction restriction : restrictions) {
final String permission = StringUtils.isBlank(restriction.getRequiredPermission())
? "Not Specified" : restriction.getRequiredPermission();
final String explanation = StringUtils.isBlank(restriction.getExplanation())
? "Not Specified" : restriction.getExplanation();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", permission);
writeSimpleElement(xmlStreamWriter, "td", explanation);
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
} else {
xmlStreamWriter.writeCharacters("This component requires access to restricted components regardless of restriction.");
}
} else {
xmlStreamWriter.writeCharacters("This component is not restricted.");
}
}
private void writeInputRequirementInfo(final Extension extension, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
final InputRequirement inputRequirement = extension.getInputRequirement();
if(inputRequirement != null) {
writeSimpleElement(xmlStreamWriter, "h3", "Input requirement: ");
switch (inputRequirement) {
case INPUT_FORBIDDEN:
xmlStreamWriter.writeCharacters("This component does not allow an incoming relationship.");
break;
case INPUT_ALLOWED:
xmlStreamWriter.writeCharacters("This component allows an incoming relationship.");
break;
case INPUT_REQUIRED:
xmlStreamWriter.writeCharacters("This component requires an incoming relationship.");
break;
default:
xmlStreamWriter.writeCharacters("This component does not have input requirement.");
break;
}
}
}
private void writeSystemResourceConsiderationInfo(final Extension extension, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
List<SystemResourceConsideration> systemResourceConsiderations = extension.getSystemResourceConsiderations();
writeSimpleElement(xmlStreamWriter, "h3", "System Resource Considerations:");
if (systemResourceConsiderations != null && systemResourceConsiderations.size() > 0) {
xmlStreamWriter.writeStartElement("table");
xmlStreamWriter.writeAttribute("id", "system-resource-considerations");
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "th", "Resource");
writeSimpleElement(xmlStreamWriter, "th", "Description");
xmlStreamWriter.writeEndElement();
for (SystemResourceConsideration systemResourceConsideration : systemResourceConsiderations) {
final String resource = StringUtils.isBlank(systemResourceConsideration.getResource())
? "Not Specified" : systemResourceConsideration.getResource();
final String description = StringUtils.isBlank(systemResourceConsideration.getDescription())
? "Not Specified" : systemResourceConsideration.getDescription();
xmlStreamWriter.writeStartElement("tr");
writeSimpleElement(xmlStreamWriter, "td", resource);
writeSimpleElement(xmlStreamWriter, "td", description);
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
} else {
xmlStreamWriter.writeCharacters("None specified.");
}
}
private void writeProvidedServiceApis(final Extension extension, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
final List<ProvidedServiceAPI> serviceAPIS = extension.getProvidedServiceAPIs();
if (serviceAPIS != null && serviceAPIS.size() > 0) {
writeSimpleElement(xmlStreamWriter, "h3", "Provided Service APIs:");
xmlStreamWriter.writeStartElement("ul");
for (final ProvidedServiceAPI serviceAPI : serviceAPIS) {
final String name = getSimpleName(serviceAPI.getClassName());
final String bundleInfo = " (" + serviceAPI.getGroupId() + "-" + serviceAPI.getArtifactId() + "-" + serviceAPI.getVersion() + ")";
xmlStreamWriter.writeStartElement("li");
xmlStreamWriter.writeCharacters(name);
xmlStreamWriter.writeStartElement("i");
xmlStreamWriter.writeCharacters(bundleInfo);
xmlStreamWriter.writeEndElement();
xmlStreamWriter.writeEndElement();
}
xmlStreamWriter.writeEndElement();
}
}
private void writeSeeAlso(final Extension extension, final XMLStreamWriter xmlStreamWriter)
throws XMLStreamException {
final List<String> seeAlsos = extension.getSeeAlso();
if (seeAlsos != null && seeAlsos.size() > 0) {
writeSimpleElement(xmlStreamWriter, "h3", "See Also:");
xmlStreamWriter.writeStartElement("ul");
for (final String seeAlso : seeAlsos) {
writeSimpleElement(xmlStreamWriter, "li", seeAlso);
}
xmlStreamWriter.writeEndElement();
}
}
/**
* Writes a begin element, then text, then end element for the element of a
* users choosing. Example: &lt;p&gt;text&lt;/p&gt;
*
* @param writer the stream writer to use
* @param elementName the name of the element
* @param characters the characters to insert into the element
* @throws XMLStreamException thrown if there was a problem writing to the
* stream
*/
protected final static void writeSimpleElement(final XMLStreamWriter writer, final String elementName,
final String characters) throws XMLStreamException {
writeSimpleElement(writer, elementName, characters, false);
}
/**
* Writes a begin element, then text, then end element for the element of a
* users choosing. Example: &lt;p&gt;text&lt;/p&gt;
*
* @param writer the stream writer to use
* @param elementName the name of the element
* @param characters the characters to insert into the element
* @param strong whether the characters should be strong or not.
* @throws XMLStreamException thrown if there was a problem writing to the
* stream.
*/
protected final static void writeSimpleElement(final XMLStreamWriter writer, final String elementName,
final String characters, boolean strong) throws XMLStreamException {
writeSimpleElement(writer, elementName, characters, strong, null);
}
/**
* Writes a begin element, an id attribute(if specified), then text, then
* end element for element of the users choosing. Example: &lt;p
* id="p-id"&gt;text&lt;/p&gt;
*
* @param writer the stream writer to use
* @param elementName the name of the element
* @param characters the text of the element
* @param strong whether to bold the text of the element or not
* @param id the id of the element. specifying null will cause no element to
* be written.
* @throws XMLStreamException xse
*/
protected final static void writeSimpleElement(final XMLStreamWriter writer, final String elementName,
final String characters, boolean strong, String id) throws XMLStreamException {
writer.writeStartElement(elementName);
if (id != null) {
writer.writeAttribute("id", id);
}
if (strong) {
writer.writeStartElement("strong");
}
writer.writeCharacters(characters);
if (strong) {
writer.writeEndElement();
}
writer.writeEndElement();
}
/**
* A helper method to write a link
*
* @param xmlStreamWriter the stream to write to
* @param text the text of the link
* @param location the location of the link
* @throws XMLStreamException thrown if there was a problem writing to the
* stream
*/
protected void writeLink(final XMLStreamWriter xmlStreamWriter, final String text, final String location)
throws XMLStreamException {
xmlStreamWriter.writeStartElement("a");
xmlStreamWriter.writeAttribute("href", location);
xmlStreamWriter.writeCharacters(text);
xmlStreamWriter.writeEndElement();
}
}