001/*
002 * Copyright (c) 2006-2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Nuxeo - initial API and implementation
011 *
012 */
013package org.nuxeo.ecm.core.convert.extension;
014
015import java.io.Serializable;
016import java.util.ArrayList;
017import java.util.HashMap;
018import java.util.List;
019import java.util.Map;
020
021import org.apache.commons.logging.Log;
022import org.apache.commons.logging.LogFactory;
023import org.nuxeo.common.xmap.annotation.XNode;
024import org.nuxeo.common.xmap.annotation.XNodeList;
025import org.nuxeo.common.xmap.annotation.XNodeMap;
026import org.nuxeo.common.xmap.annotation.XObject;
027
028/**
029 * XMap descriptor for the contribution of a new {@link Converter}.
030 *
031 * @author tiry
032 */
033@XObject("converter")
034public class ConverterDescriptor implements Serializable {
035
036    protected final Log log = LogFactory.getLog(ConverterDescriptor.class);
037
038    private static final long serialVersionUID = 1L;
039
040    public static final String CUSTOM_CONVERTER_TYPE = "Custom";
041
042    public static final String CHAINED_CONVERTER_TYPE = "Chain";
043
044    protected Converter instance;
045
046    @XNode("@name")
047    protected String converterName;
048
049    @XNodeList(value = "sourceMimeType", type = ArrayList.class, componentType = String.class)
050    protected List<String> sourceMimeTypes = new ArrayList<>();
051
052    @XNode("destinationMimeType")
053    protected String destinationMimeType;
054
055    @XNode("@class")
056    protected Class className;
057
058    @XNode("@type")
059    protected String converterType = CUSTOM_CONVERTER_TYPE;
060
061    protected boolean wrappedTransformer = false;
062
063    @XNodeMap(value = "parameters/parameter", key = "@name", type = HashMap.class, componentType = String.class)
064    protected Map<String, String> parameters = new HashMap<>();
065
066    @XNodeList(value = "conversionSteps/step", type = ArrayList.class, componentType = String.class)
067    protected List<String> steps = new ArrayList<>();
068
069    @XNodeList(value = "conversionSteps/subconverter", type = ArrayList.class, componentType = String.class)
070    protected List<String> subConverters = new ArrayList<>();
071
072    public String getConverterName() {
073        return converterName;
074    }
075
076    public List<String> getSourceMimeTypes() {
077        return sourceMimeTypes;
078    }
079
080    public List<String> getSteps() {
081        return steps;
082    }
083
084    public String getDestinationMimeType() {
085        return destinationMimeType;
086    }
087
088    public void initConverter() {
089        if (instance == null) {
090            if (className == null || converterType.equals(CHAINED_CONVERTER_TYPE)) {
091
092                if (subConverters == null || subConverters.isEmpty()) {
093                    // create a Chained converter based on mimetypes
094                    instance = new ChainedConverter();
095                } else {
096                    // create a Chained converter based on converter chain
097                    instance = new ChainedConverter(subConverters);
098                }
099                converterType = CHAINED_CONVERTER_TYPE;
100            } else {
101                try {
102                    instance = (Converter) className.newInstance();
103                } catch (ReflectiveOperationException e) {
104                    throw new RuntimeException(e);
105                }
106            }
107            instance.init(this);
108        }
109    }
110
111    public Converter getConverterInstance() {
112        initConverter();
113        return instance;
114    }
115
116    public Map<String, String> getParameters() {
117        return parameters;
118    }
119
120    public ConverterDescriptor merge(ConverterDescriptor other) {
121
122        if (!other.converterName.equals(converterName)) {
123            throw new UnsupportedOperationException("Can not merge ConverterDesciptors with different names");
124        }
125
126        if (wrappedTransformer) {
127            // converter completely override wrapped transformers
128            return other;
129        }
130
131        if (other.parameters != null) {
132            parameters.putAll(other.parameters);
133        }
134        if (other.className != null) {
135            instance = null;
136            className = other.className;
137        }
138        if (other.sourceMimeTypes != null) {
139            for (String mt : other.sourceMimeTypes) {
140                if (!sourceMimeTypes.contains(mt)) {
141                    sourceMimeTypes.add(mt);
142                }
143
144            }
145            // sourceMimeTypes.addAll(other.sourceMimeTypes);
146        }
147        if (other.destinationMimeType != null) {
148            destinationMimeType = other.destinationMimeType;
149        }
150        if (other.converterType != null) {
151            converterType = other.converterType;
152        }
153        if (other.steps != null && !other.steps.isEmpty()) {
154            steps = other.steps;
155        }
156
157        return this;
158    }
159
160    public String getConverterType() {
161        return converterType;
162    }
163
164}