de.fhg.iais.asc.xslt.binaries.DownloadAndScale.java Source code

Java tutorial

Introduction

Here is the source code for de.fhg.iais.asc.xslt.binaries.DownloadAndScale.java

Source

package de.fhg.iais.asc.xslt.binaries;

/******************************************************************************
 * Copyright 2011 (c) Fraunhofer IAIS Netmedia  http://www.iais.fraunhofer.de *
 * ************************************************************************** *
 * 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.                                             *
 ******************************************************************************/

import java.io.File;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import de.fhg.iais.asc.commons.AscConfiguration;
import de.fhg.iais.asc.commons.exceptions.AscTechnicalErrorException;
import de.fhg.iais.asc.directories.AscDirectory;
import de.fhg.iais.asc.transformer.TransformationContext;
import de.fhg.iais.asc.xslt.binaries.download.Downloader;
import de.fhg.iais.asc.xslt.binaries.scale.conf.ConfBinariesXML;
import de.fhg.iais.asc.xslt.binaries.scale.conf.PreviewImageType;
import de.fhg.iais.asc.xslt.binaries.util.DOMAttributes;
import de.fhg.iais.commons.annotation.UsedBy;

public class DownloadAndScale extends DownloadAndScaleContext {
    // <set-parameters> element and attributes
    static final String ELEMNAME_SET_PARAMS = "set-parameters";
    static final String PARAMNAME_RESULT_PATH = "result_path";

    // <binary> element and attributes
    static final String ELEMNAME_BINARY = "binary";
    static final String ATTRNAME_PATH = "path";
    static final String ATTRNAME_MIMETYPE = "mimetype";
    static final String ATTRNAME_POSITION = "position";
    static final String ATTRNAME_PRIMARY = "primary";
    static final String ATTRNAME_CATEGORY = "category";
    static final String ATTRNAME_LOCAL_PATH = "local_path";
    static final String ATTRNAME_NAME = "name";
    static final String ATTRNAME_NAME2 = "name2";
    static final String ATTRNAME_NAME3 = "name3";
    static final String ATTRNAME_FULL = "full";

    static final String ATTRNAME_URL = "url";
    static final String ATTRNAME_LOCAL_PATHNAME = "local_pathname";

    private static final Pattern NON_ALNUM = Pattern.compile("[^\\p{Alnum}]");

    private static final List<String> ATTRNAMES_COPY_TO_RESULT = Arrays.asList(ATTRNAME_POSITION, ATTRNAME_NAME,
            ATTRNAME_NAME2, ATTRNAME_NAME3, ATTRNAME_MIMETYPE, ATTRNAME_PRIMARY);

    private final Document targetDoc;

    @UsedBy("XSLT (transformers/common/workflow/binaries.xsl)")
    public static Node downloadAndScale(String contextId, Node binaries) {
        TransformationContext transContext = TransformationContext.fromId(contextId);
        if (transContext != null) {
            try {
                return new DownloadAndScale(transContext).apply(binaries);
            } catch (Exception e) {
                throw AscTechnicalErrorException.wrap("DownloadAndScale failed", e);
            }
        }

        throw new AscTechnicalErrorException("Invalid transformation context in call to DownloadAndScale");
    }

    DownloadAndScale(TransformationContext transContext) {
        super(transContext, getBinaryRoot(transContext), new HashMap<String, String>());

        try {
            // where is the DocumentBuilderFactoryBuilderFactoryFactory when you need it?
            this.targetDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("Error constructing DOM document", e);
        }
    }

    private static File getBinaryRoot(TransformationContext transContext) {
        return transContext.getDirectories().checkedGetDirectory(AscDirectory.BINARIES);
    }

    Node apply(Node binaries) {
        Node result = this.targetDoc.createDocumentFragment();

        NodeList children = binaries.getChildNodes();

        int length = children.getLength();
        for (int i = 0; i < length; ++i) {
            Node item = children.item(i);

            String itemName = item.getNodeName();

            try {
                if (itemName.equals(ELEMNAME_SET_PARAMS)) {
                    handleSetParameters(item);
                } else if (itemName.equals(ELEMNAME_BINARY)) {
                    List<Node> nodes = handleBinary(item);
                    for (Node resultBinary : nodes) {
                        result.appendChild(resultBinary);
                    }
                }
            } catch (AscTechnicalErrorException e) {
                if (this.ascContext.get(AscConfiguration.BINARIES_CONTINUE_ON_FAIL, false)) {
                    continue;
                } else {
                    throw e;
                }
            }
        }

        this.parameters.clear();

        return result;
    }

    private void handleSetParameters(Node item) {
        NamedNodeMap attrMap = item.getAttributes();
        int i = attrMap.getLength();
        while (i-- > 0) {
            Node attrNode = attrMap.item(i);
            this.parameters.put(attrNode.getNodeName(), attrNode.getNodeValue());
        }
    }

    private List<Node> handleBinary(Node binaryNode) {
        DownloadAndScaleBinary transBinary = createTransformBinary(binaryNode);
        if (transBinary == null) {
            return Collections.emptyList();
        }

        List<Node> result = new LinkedList<Node>();

        String typeSubPath = transBinary.getTypeSubPath();
        List<PreviewImageType> previewTypes = ConfBinariesXML.getBinariesConfiguration().previewTypes;
        List<Object> list = transBinary.createAllVariants(previewTypes);
        String origMimeType = transBinary.getMimeType();
        for (Object variant : list) {
            String variantMimeType = null;
            if ((variant instanceof URI) || ((variant instanceof String) && ((String) variant).startsWith("full/"))
                    || "video/vimeo".equals(origMimeType)) {
                variantMimeType = origMimeType;
            } else {
                variantMimeType = "image/jpeg";
            }
            addBinaryNodeWithPath(result, binaryNode, variant, typeSubPath, variantMimeType);
        }

        return result;
    }

    private DownloadAndScaleBinary createTransformBinary(Node binary) {
        final String url = DOMAttributes.get(binary, ATTRNAME_URL);
        final String localPathname = DOMAttributes.get(binary, ATTRNAME_LOCAL_PATHNAME);

        if (StringUtils.isEmpty(url) && StringUtils.isEmpty(localPathname)) {
            return createTransformBinaryOld(binary);
        }

        final URI uri = Downloader.createDownloadableURI(url);

        String mimeType = DOMAttributes.get(binary, ATTRNAME_MIMETYPE);
        boolean primary = DOMAttributes.getBoolean(binary, ATTRNAME_PRIMARY);

        boolean full = true;
        String fullStr = DOMAttributes.get(binary, ATTRNAME_FULL);
        if (fullStr != null) {
            full = Boolean.parseBoolean(fullStr);
        }

        return new DownloadAndScaleBinary(this, uri, localPathname, primary, full).setMimeType(mimeType);
    }

    private DownloadAndScaleBinary createTransformBinaryOld(Node binary) {
        String binaryPathOrUrl = DOMAttributes.get(binary, ATTRNAME_PATH);
        if (StringUtils.isEmpty(binaryPathOrUrl)) {
            return null;
        }

        String localPath = DOMAttributes.get(binary, ATTRNAME_LOCAL_PATH);
        String mimeType = DOMAttributes.get(binary, ATTRNAME_MIMETYPE);
        boolean primary = DOMAttributes.getBoolean(binary, ATTRNAME_PRIMARY);
        boolean full = true;
        String fullStr = DOMAttributes.get(binary, ATTRNAME_FULL);
        if (fullStr != null) {
            full = Boolean.parseBoolean(fullStr);
        }

        return new DownloadAndScaleBinary(this, binaryPathOrUrl, localPath, primary, full).setMimeType(mimeType);
    }

    private void addBinaryNodeWithPath(List<Node> result, Node inputNode, Object variant, String subPath,
            String mimeType) {
        final Element binaryElement = this.targetDoc.createElement("binary");
        copyAttributes(inputNode, binaryElement, ATTRNAMES_COPY_TO_RESULT);

        if (variant instanceof URI) {
            binaryElement.setAttribute(ATTRNAME_PATH, variant.toString());
        } else {
            String resultPath = this.parameters.get(PARAMNAME_RESULT_PATH);
            if (StringUtils.isNotEmpty(resultPath)) {
                binaryElement.setAttribute(PARAMNAME_RESULT_PATH, resultPath);
            }

            binaryElement.setAttribute(ATTRNAME_LOCAL_PATHNAME, (String) variant);

            if (mimeType.startsWith("video/") || mimeType.startsWith("audio/")) { //  Todo Test anpassen
                binaryElement.setAttribute(ATTRNAME_CATEGORY, "full");
            }

            if (!mimeType.equals("video/vimeo")) {
                String prefix = FilenameUtils.removeExtension((String) variant)
                        .replace(FilenameUtils.removeExtension(subPath), "");
                binaryElement.setAttribute(ATTRNAME_PATH,
                        prefix + binaryElement.getAttribute(ATTRNAME_POSITION) + getExtension((String) variant));

                if (mimeType.startsWith("image/") || mimeType.equals("application/pdf")) { //  ToDo Test anpassen

                    binaryElement.setAttribute(ATTRNAME_CATEGORY, prefix.replace("/", ""));
                }

            } else {
                binaryElement.setAttribute(ATTRNAME_PATH, (String) variant);
            }
        }

        binaryElement.setAttribute(ATTRNAME_MIMETYPE, mimeType);

        //  binaryElement.setAttribute(ATTRNAME_FULL, full);

        result.add(binaryElement);
    }

    private String getExtension(String relativePath) {
        String extension = FilenameUtils.getExtension(relativePath);
        if (StringUtils.isEmpty(extension)) {
            return "";
        }

        extension = NON_ALNUM.matcher(extension).replaceAll("").toLowerCase(Locale.ENGLISH);
        return extension.isEmpty() ? "" : ("." + extension);
    }

    private static void copyAttributes(Node source, Element target, Iterable<String> attributeNames) {
        final NamedNodeMap sourceAttributes = source.getAttributes();

        if (sourceAttributes != null) {
            for (String attrName : attributeNames) {
                final Node inputAttr = sourceAttributes.getNamedItem(attrName);

                if (inputAttr != null) {
                    target.setAttribute(attrName, inputAttr.getNodeValue());
                }
            }
        }
    }
}