001/*
002 * (C) Copyright 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 *     Anahide Tchertchian
018 */
019package org.nuxeo.ecm.automation.io.yaml;
020
021import static org.nuxeo.ecm.automation.core.Constants.T_PROPERTIES;
022
023import java.io.IOException;
024import java.util.HashMap;
025import java.util.LinkedHashMap;
026import java.util.List;
027import java.util.Map;
028
029import org.nuxeo.ecm.automation.OperationDocumentation;
030import org.nuxeo.ecm.automation.OperationDocumentation.Param;
031import org.nuxeo.ecm.automation.core.OperationChainContribution;
032import org.nuxeo.ecm.automation.core.OperationChainContribution.Operation;
033import org.nuxeo.ecm.automation.core.util.Properties;
034import org.yaml.snakeyaml.DumperOptions.FlowStyle;
035import org.yaml.snakeyaml.nodes.Node;
036import org.yaml.snakeyaml.nodes.Tag;
037import org.yaml.snakeyaml.representer.Represent;
038import org.yaml.snakeyaml.representer.Representer;
039
040/**
041 * YAML representer for automation chains.
042 *
043 * @since 5.9.4
044 */
045public class YamlAutomationRepresenter extends Representer {
046
047    public YamlAutomationRepresenter() {
048        super();
049        this.addClassTag(OperationDocumentation.class, Tag.MAP);
050        this.representers.put(OperationDocumentation.class, new ChainRepr());
051        this.addClassTag(Operation.class, Tag.MAP);
052        this.representers.put(Operation.class, new OpRepr());
053        this.addClassTag(Param.class, Tag.MAP);
054        this.representers.put(Param.class, new ParamRepr());
055    }
056
057    public class ChainRepr implements Represent {
058        @Override
059        public Node representData(Object data) {
060            OperationDocumentation c = (OperationDocumentation) data;
061            Tag tag = getTag(OperationDocumentation.class, null);
062            Map<Object, Object> mapping = new LinkedHashMap<>();
063            if (c.getDescription() != null) {
064                mapping.put("description", c.getDescription());
065            }
066            if (c.getParams() != null && c.getParams().length != 0) {
067                mapping.put("params", c.getParams());
068            }
069            Operation[] ops = c.getOperations();
070            if (ops != null && ops.length != 0) {
071                if (mapping.isEmpty()) {
072                    // omit the "operations" parent if params and description
073                    // are empty
074                    return YamlAutomationRepresenter.this.representData(ops);
075                }
076                mapping.put("operations", ops);
077            }
078            return representMapping(tag, mapping, FlowStyle.AUTO);
079        }
080    }
081
082    public class OpRepr implements Represent {
083
084        @Override
085        public Node representData(Object data) {
086            Operation op = (Operation) data;
087            Tag tag = getTag(Operation.class, null);
088            List<OperationChainContribution.Param> params = op.getParams();
089            if (params != null && !params.isEmpty()) {
090                Map<Object, Object> mapping = new HashMap<>();
091                Map<Object, Object> subs = new LinkedHashMap<>();
092                for (OperationChainContribution.Param param : params) {
093                    // handle java properties use case
094                    if (T_PROPERTIES.equals(param.getType())) {
095                        if (param.getMap() != null && !param.getMap().isEmpty()) {
096                            Properties props = new Properties(param.getMap());
097                            subs.put(param.getName(), props);
098                        } else {
099                            try {
100                                Properties props = new Properties(param.getValue());
101                                subs.put(param.getName(), props);
102                            } catch (IOException e) {
103                                subs.put(param.getName(), param.getValue());
104                            }
105                        }
106                    } else {
107                        subs.put(param.getName(), param.getValue());
108                    }
109                }
110                mapping.put(op.getId(), subs);
111                return representMapping(tag, mapping, FlowStyle.AUTO);
112            } else {
113                return YamlAutomationRepresenter.this.representData(op.getId());
114            }
115        }
116    }
117
118    public class ParamRepr implements Represent {
119        @Override
120        public Node representData(Object data) {
121            Param p = (Param) data;
122            Tag tag = getTag(Param.class, null);
123            Map<Object, Object> mapping = new HashMap<>();
124            Map<Object, Object> subs = new LinkedHashMap<>();
125            subs.put("type", p.getType());
126            if (p.getDescription() != null) {
127                subs.put("description", p.getDescription());
128            }
129            if (p.getValues() != null && p.getValues().length != 0) {
130                subs.put("values", p.getValues());
131            }
132            mapping.put(p.getName(), subs);
133            return representMapping(tag, mapping, FlowStyle.AUTO);
134        }
135    }
136
137}