/** * DataCleaner (community edition) * Copyright (C) 2014 Neopost - Customer Information Management * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.datacleaner.documentation; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.EnumSet; import java.util.Set; import javax.imageio.ImageIO; import org.apache.commons.codec.binary.Base64; import org.apache.metamodel.util.FileHelper; import org.datacleaner.api.AnalyzerResult; import org.datacleaner.api.ComponentCategory; import org.datacleaner.api.Concurrent; import org.datacleaner.api.ExternalDocumentation; import org.datacleaner.api.HasAnalyzerResult; import org.datacleaner.api.QueryOptimizedFilter; import org.datacleaner.descriptors.AnalyzerDescriptor; import org.datacleaner.descriptors.ComponentDescriptor; import org.datacleaner.descriptors.FilterDescriptor; import org.datacleaner.descriptors.HasAnalyzerResultComponentDescriptor; import org.datacleaner.descriptors.MetricDescriptor; import org.datacleaner.descriptors.SimpleHasAnalyzerResultComponentDescriptor; import org.datacleaner.descriptors.TransformerDescriptor; import org.datacleaner.util.IconUtils; import org.datacleaner.util.ReflectionUtils; import org.datacleaner.util.StringUtils; /** * A wrapper around the {@link ComponentDescriptor} object to make it easier for * the documentation template to get to certain aspects that should be presented * in the documentation. */ public class ComponentDocumentationWrapper { private static final String HTMLBASE64_PREFIX = "data:image/png;base64,"; private final ComponentDescriptor<?> _componentDescriptor; public ComponentDocumentationWrapper(final ComponentDescriptor<?> componentDescriptor) { _componentDescriptor = componentDescriptor; } public String getName() { return _componentDescriptor.getDisplayName(); } public String getDescription() { return DocumentationUtils.createHtmlParagraphs(_componentDescriptor.getDescription()); } public String getSuperCategory() { return _componentDescriptor.getComponentSuperCategory().getName(); } public ComponentDescriptor<?> getComponentDescriptor() { return _componentDescriptor; } public String[] getCategories() { final Set<ComponentCategory> componentCategories = _componentDescriptor.getComponentCategories(); final ComponentCategory[] array = componentCategories.toArray(new ComponentCategory[componentCategories.size()]); final String[] result = new String[componentCategories.size()]; for (int i = 0; i < result.length; i++) { result[i] = array[i].getName(); } return result; } public boolean isQueryOptimizable() { return ReflectionUtils.is(_componentDescriptor.getComponentClass(), QueryOptimizedFilter.class); } public ExternalDocumentation.DocumentationLink[] getDocumentationLinks() { final ExternalDocumentation externalDocumentation = _componentDescriptor.getAnnotation(ExternalDocumentation.class); if (externalDocumentation == null) { return new ExternalDocumentation.DocumentationLink[0]; } return externalDocumentation.value(); } public String[] getAliases() { return _componentDescriptor.getAliases(); } public boolean isDistributable() { return _componentDescriptor.isDistributable(); } public boolean isConcurrent() { final Concurrent annotation = _componentDescriptor.getAnnotation(Concurrent.class); if (annotation != null) { return annotation.value(); } if (isAnalyzer()) { return false; } return true; } public String getIconSrc(final int width) throws IOException { // Attach the image final Image descriptorIcon = IconUtils.getDescriptorIcon(_componentDescriptor, width).getImage(); /* We need a buffered image type in order to obtain the */ final BufferedImage bufferedImage = ComponentDocumentationBuilder.toBufferedImage(descriptorIcon); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final byte[] imageInByte; try { ImageIO.write(bufferedImage, "png", baos); imageInByte = baos.toByteArray(); } finally { FileHelper.safeClose(baos); } /* Encode the image */ final String encodedImage = Base64.encodeBase64String(imageInByte); /* * Atach the prefix that will make html <img> know how to decode the * image */ return HTMLBASE64_PREFIX + encodedImage; } public int getIconSizeLarge() { return IconUtils.ICON_SIZE_LARGE; } public boolean isAnalyzer() { return _componentDescriptor instanceof AnalyzerDescriptor; } public boolean isTransformer() { return _componentDescriptor instanceof TransformerDescriptor; } public boolean isFilter() { return _componentDescriptor instanceof FilterDescriptor; } public boolean isResultProducer() { return ReflectionUtils.is(_componentDescriptor.getComponentClass(), HasAnalyzerResult.class); } public String getResultType() { final HasAnalyzerResultComponentDescriptor<?> descriptor = getHasAnalyzerResultComponentDescriptor(); final Class<? extends AnalyzerResult> resultClass = descriptor.getResultClass(); return resultClass.getSimpleName(); } public MetricDocumentationWrapper[] getMetrics() { final HasAnalyzerResultComponentDescriptor<?> descriptor = getHasAnalyzerResultComponentDescriptor(); final Set<MetricDescriptor> metrics = descriptor.getResultMetrics(); final MetricDocumentationWrapper[] result = new MetricDocumentationWrapper[metrics.size()]; int i = 0; for (final MetricDescriptor metricDescriptor : metrics) { result[i] = new MetricDocumentationWrapper(metricDescriptor); i++; } return result; } private HasAnalyzerResultComponentDescriptor<?> getHasAnalyzerResultComponentDescriptor() { if (_componentDescriptor instanceof HasAnalyzerResultComponentDescriptor) { return (HasAnalyzerResultComponentDescriptor<?>) _componentDescriptor; } @SuppressWarnings("unchecked") final Class<? extends HasAnalyzerResult<?>> componentClass = (Class<? extends HasAnalyzerResult<?>>) _componentDescriptor.getComponentClass(); return new SimpleHasAnalyzerResultComponentDescriptor<>(componentClass); } public FilterOutcomeDocumentationWrapper[] getFilterOutcomes() { if (_componentDescriptor instanceof FilterDescriptor) { final EnumSet<?> outcomes = ((FilterDescriptor<?, ?>) _componentDescriptor).getOutcomeCategories(); final FilterOutcomeDocumentationWrapper[] result = new FilterOutcomeDocumentationWrapper[outcomes.size()]; int i = 0; for (final Enum<?> outcome : outcomes) { result[i] = new FilterOutcomeDocumentationWrapper(outcome); i++; } return result; } return new FilterOutcomeDocumentationWrapper[0]; } /** * Gets the "href" attribute content if a link to this component should be * made from elsewhere in the component docs. * * @return */ public String getHref() { final String displayName = _componentDescriptor.getDisplayName(); final String filename = StringUtils.replaceWhitespaces(displayName.toLowerCase().trim(), "_").replaceAll("\\/", "_") .replaceAll("\\\\", "_"); return filename + ".html"; } }