001/*
002 * (C) Copyright 2006-2010 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 *     bstefanescu
018 */
019package org.nuxeo.shell.automation.cmds;
020
021import java.io.File;
022import java.util.ArrayList;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import jline.Completor;
028
029import org.nuxeo.ecm.automation.client.model.DocRef;
030import org.nuxeo.ecm.automation.client.model.FileBlob;
031import org.nuxeo.ecm.automation.client.model.OperationDocumentation;
032import org.nuxeo.ecm.automation.client.model.OperationDocumentation.Param;
033import org.nuxeo.ecm.automation.client.model.OperationInput;
034import org.nuxeo.shell.Shell;
035import org.nuxeo.shell.ShellException;
036import org.nuxeo.shell.automation.DocRefCompletor;
037import org.nuxeo.shell.fs.FileCompletor;
038import org.nuxeo.shell.impl.AbstractCommandType;
039
040/**
041 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
042 */
043public class OperationCommandType extends AbstractCommandType {
044
045    public static final int TYPE_VOID = 0;
046
047    public static final int TYPE_DOC = 1;
048
049    public static final int TYPE_BLOB = 2;
050
051    public static final int TYPE_DOCS = 3;
052
053    public static final int TYPE_BLOBS = 4;
054
055    protected OperationDocumentation op;
056
057    protected int inputType = 0;
058
059    public boolean hasVoidInput() {
060        return inputType == 0;
061    }
062
063    public boolean hasBlobInput() {
064        return inputType == 2;
065    }
066
067    public boolean hasDocumentInput() {
068        return inputType == 1;
069    }
070
071    public int getInputType() {
072        return inputType;
073    }
074
075    public static OperationCommandType fromOperation(OperationDocumentation op) {
076        int inputType = 0;
077        HashMap<String, Token> params = new HashMap<String, Token>();
078        ArrayList<Token> args = new ArrayList<Token>();
079
080        Token tok = new Token();
081        tok.name = "-void";
082        tok.help = "If void the server will not return the result back";
083        tok.isRequired = false;
084        tok.setter = new OperationParamSetter(tok.name, "boolean");
085        params.put(tok.name, tok);
086        tok = new Token();
087        tok.name = "-ctx";
088        tok.help = "Can be used to inject context properties in Java properties format";
089        tok.isRequired = true;
090        tok.setter = new OperationParamSetter(tok.name, "string");
091        params.put(tok.name, tok);
092
093        for (Param param : op.getParams()) {
094            tok = new Token();
095            tok.name = "-" + param.name;
096            tok.help = "";
097            tok.isRequired = true;
098            OperationParamSetter os = new OperationParamSetter(param.name, param.getType());
099            tok.setter = os;
100            tok.completor = os.completor;
101            params.put(tok.name, tok);
102        }
103
104        inputType = getOperationInputType(op);
105        if (inputType == TYPE_DOC || inputType == TYPE_DOCS) {
106            tok = new Token();
107            tok.index = 0;
108            tok.isRequired = false;
109            tok.name = "the input document(s)";
110            tok.setter = new DocInputSetter();
111            tok.completor = DocRefCompletor.class;
112            args.add(tok);
113        } else if (inputType == TYPE_BLOB || inputType == TYPE_BLOBS) {
114            tok = new Token();
115            tok.index = 0;
116            tok.isRequired = true;
117            tok.name = "the input file(s)";
118            tok.setter = new BlobInputSetter();
119            tok.completor = FileCompletor.class;
120            args.add(tok);
121        }
122        return new OperationCommandType(inputType, op, params, args);
123    }
124
125    public static int getOperationInputType(OperationDocumentation op) {
126        for (int i = 0; i < op.signature.length; i += 2) {
127            if ("void".equals(op.signature[i])) {
128                return TYPE_VOID;
129            }
130            if ("document".equals(op.signature[i])) {
131                return TYPE_DOC;
132            }
133            if ("blob".equals(op.signature[i])) {
134                return TYPE_BLOB;
135            }
136            if ("documents".equals(op.signature[i])) {
137                return TYPE_DOCS;
138            }
139            if ("bloblist".equals(op.signature[i])) {
140                return TYPE_BLOBS;
141            }
142        }
143        return TYPE_VOID;
144    }
145
146    public OperationCommandType(int inputType, OperationDocumentation op, Map<String, Token> params, List<Token> args) {
147        super(OperationCommand.class, null, params, args);
148        this.op = op;
149        this.inputType = inputType;
150    }
151
152    public String getHelp() {
153        return op.description;
154    }
155
156    public String[] getAliases() {
157        return new String[0];
158    }
159
160    public String getName() {
161        return op.id;
162    }
163
164    @Override
165    protected Runnable createInstance(Shell shell) throws Exception {
166        OperationCommand cmd = (OperationCommand) cmdClass.newInstance();
167        cmd.init(this, shell, op);
168        return cmd;
169    }
170
171    public static class OperationParamSetter implements Setter {
172        protected String name;
173
174        protected Class<?> type;
175
176        protected Class<? extends Completor> completor;
177
178        public OperationParamSetter(String name, String type) {
179            this.name = name;
180            if ("document".equals(type)) {
181                this.type = DocRef.class;
182                this.completor = DocRefCompletor.class;
183            } else if ("blob".equals(type)) {
184                this.type = File.class;
185                this.completor = FileCompletor.class;
186            } else {
187                this.type = String.class;
188            }
189        }
190
191        public Class<?> getType() {
192            return type;
193        }
194
195        public void set(Object obj, Object value) throws ShellException {
196            if (value instanceof File) {
197                value = new FileBlob((File) value);
198            }
199            ((OperationCommand) obj).setParam(name, value);
200        }
201    }
202
203    public static class DocInputSetter implements Setter {
204
205        public Class<?> getType() {
206            return DocRef.class;
207        }
208
209        public void set(Object obj, Object value) throws ShellException {
210            ((OperationCommand) obj).request.setInput((OperationInput) value);
211        }
212    }
213
214    public static class BlobInputSetter implements Setter {
215        public Class<?> getType() {
216            return File.class;
217        }
218
219        public void set(Object obj, Object value) throws ShellException {
220            ((OperationCommand) obj).request.setInput(new FileBlob((File) value));
221        }
222
223    }
224
225}