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