001/*
002 * (C) Copyright 2006-2011 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.ecm.automation.client.jaxrs.spi;
020
021import java.io.IOException;
022import java.text.SimpleDateFormat;
023import java.util.ArrayList;
024import java.util.Calendar;
025import java.util.Date;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029
030import org.nuxeo.ecm.automation.client.OperationRequest;
031import org.nuxeo.ecm.automation.client.Session;
032import org.nuxeo.ecm.automation.client.model.DateUtils;
033import org.nuxeo.ecm.automation.client.model.Document;
034import org.nuxeo.ecm.automation.client.model.OperationDocumentation;
035import org.nuxeo.ecm.automation.client.model.OperationDocumentation.Param;
036import org.nuxeo.ecm.automation.client.model.OperationInput;
037
038/**
039 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
040 */
041public class DefaultOperationRequest implements OperationRequest {
042
043    protected final OperationDocumentation op;
044
045    protected final Session session;
046
047    protected final Map<String, Object> params;
048
049    protected final Map<String, Object> ctx;
050
051    protected final Map<String, String> headers;
052
053    protected Object input;
054
055    public DefaultOperationRequest(Session session, OperationDocumentation op) {
056        this(session, op, new HashMap<String, Object>());
057    }
058
059    public DefaultOperationRequest(Session session, OperationDocumentation op, Map<String, Object> ctx) {
060        this.session = session;
061        this.op = op;
062        params = new HashMap<String, Object>();
063        headers = new HashMap<String, String>();
064        this.ctx = ctx;
065    }
066
067    public Session getSession() {
068        return session;
069    }
070
071    protected final boolean acceptInput(String type) {
072        for (int i = 0, size = op.signature.length; i < size; i += 2) {
073            if ("void".equals(op.signature[i])) {
074                return true;
075            }
076            if (type.equals(op.signature[i])) {
077                return true;
078            }
079        }
080        return false;
081    }
082
083    protected final void checkInput(String type) {
084        if (!acceptInput(type)) {
085            throw new IllegalArgumentException("Input not supported: " + type + " for the operation: " + op.id);
086        }
087    }
088
089    public List<String> getParamNames() {
090        List<String> result = new ArrayList<String>();
091        for (Param param : op.params) {
092            result.add(param.name);
093        }
094        return result;
095    }
096
097    public Param getParam(String key) {
098        for (Param param : op.params) {
099            if (key.equals(param.name)) {
100                return param;
101            }
102        }
103        return null;
104    }
105
106    public OperationRequest setInput(Object input) {
107        if (input == null) {
108            checkInput("void");
109        } else if (input instanceof OperationInput) {
110            checkInput(((OperationInput) input).getInputType());
111        }
112        this.input = input;
113        return this;
114    }
115
116    public Object getInput() {
117        return input;
118    }
119
120    public String getUrl() {
121        return session.getClient().getBaseUrl() + op.url;
122    }
123
124    public OperationRequest set(String key, Object value) {
125        Param param = getParam(key);
126        if (param == null) {
127            throw new IllegalArgumentException("No such parameter '" + key + "' for operation " + op.id
128                    + ".\n\tAvailable params: " + getParamNames());
129        }
130        if (value == null) {
131            params.remove(key);
132            return this;
133        }
134        // handle strings and primitive differently
135        // TODO
136        // if (!param.type.equals(value.getParamType())) {
137        // throw new
138        // IllegalArgumentException("Invalid parameter type:
139        // "+value.getParamType());
140        // }
141        if (value.getClass() == Date.class) {
142            params.put(key, DateUtils.formatDate((Date) value));
143        } else if (value instanceof Calendar){
144            params.put(key, DateUtils.formatDate(((Calendar) value).getTime()));
145        } else if ("properties".equals(key) && value instanceof Document) {
146            // Handle document parameter in case of properties - and bind it to
147            // properties
148            List<Param> parameters = op.getParams();
149            for (Param parameter : parameters) {
150                // Check if one of params has the Properties type
151                if ("properties".equals(parameter.getType())) {
152                    params.put("properties", ((Document) value).getDirties().toString());
153                }
154            }
155        } else {
156            params.put(key, value);
157        }
158        return this;
159    }
160
161    public OperationRequest setContextProperty(String key, Object value) {
162        ctx.put(key, value);
163        return this;
164    }
165
166    public Map<String, Object> getContextParameters() {
167        return ctx;
168    }
169
170    public Map<String, Object> getParameters() {
171        return params;
172    }
173
174    public Object execute() throws IOException {
175        return session.execute(this);
176    }
177
178    public OperationRequest setHeader(String key, String value) {
179        headers.put(key, value);
180        return this;
181    }
182
183    public Map<String, String> getHeaders() {
184        return headers;
185    }
186
187    @Override
188    public OperationDocumentation getOperation() {
189        return op;
190    }
191
192}