com.imaginary.home.cloud.api.call.CommandCall.java Source code

Java tutorial

Introduction

Here is the source code for com.imaginary.home.cloud.api.call.CommandCall.java

Source

/*
 * Copyright (C) 2013 George Reese
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.imaginary.home.cloud.api.call;

import com.imaginary.home.cloud.ControllerRelay;
import com.imaginary.home.cloud.Location;
import com.imaginary.home.cloud.PendingCommand;
import com.imaginary.home.cloud.PendingCommandState;
import com.imaginary.home.cloud.api.APICall;
import com.imaginary.home.cloud.api.RestApi;
import com.imaginary.home.cloud.api.RestException;
import com.imaginary.home.cloud.device.Device;
import com.imaginary.home.cloud.user.User;
import org.dasein.persist.PersistenceException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * [Class Documentation]
 * <p>Created by George Reese: 1/27/13 12:28 PM</p>
 *
 * @author George Reese
 */
public class CommandCall extends APICall {

    static public Map<String, Object> toJSON(PendingCommand cmd) throws PersistenceException {
        HashMap<String, Object> json = new HashMap<String, Object>();
        Long t;

        json.put("commandId", cmd.getPendingCommandId());
        json.put("timeout", cmd.getTimeout());
        json.put("groupId", cmd.getGroupId());
        json.put("command", cmd.getCommand());
        json.put("state", cmd.getState().name());
        json.put("issuedTimestamp", cmd.getIssuedTimestamp());
        json.put("issuedBy", cmd.getIssuedBy());

        Boolean b = cmd.getResult();

        if (b != null) {
            json.put("result", b);
        }
        String error = cmd.getErrorMessage();

        if (error != null) {
            json.put("errorMessage", error);
        }
        t = cmd.getSentTimestamp();
        if (t != null) {
            json.put("sentTimestamp", t);
        }
        t = cmd.getCompletionTimestamp();
        if (t != null) {
            json.put("completionTimestamp", t);
        }
        ArrayList<Map<String, Object>> devices = new ArrayList<Map<String, Object>>();

        for (String id : cmd.getDeviceIds()) {
            Device device = Device.getDevice(id);

            if (device != null) {
                HashMap<String, Object> d = new HashMap<String, Object>();

                d.put("deviceId", device.getVendorDeviceId());
                d.put("systemId", device.getHomeAutomationSystemId());
                devices.add(d);
            }
        }
        json.put("devices", devices);
        return json;
    }

    @Override
    public void get(@Nonnull String requestId, @Nullable String userId, @Nonnull String[] path,
            @Nonnull HttpServletRequest req, @Nonnull HttpServletResponse resp,
            @Nonnull Map<String, Object> headers, @Nonnull Map<String, Object> parameters)
            throws RestException, IOException {
        try {
            ArrayList<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
            Boolean hasCommands = null;

            if (userId == null) {
                String apiKey = (String) headers.get(RestApi.API_KEY);
                ControllerRelay relay = ControllerRelay.getRelay(apiKey);

                if (relay == null) {
                    throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                            RestException.INTERNAL_ERROR, "Relay was lost");
                }
                for (PendingCommand cmd : PendingCommand.getCommandsToSend(relay, true)) {
                    list.add(toJSON(cmd));
                }
                hasCommands = PendingCommand.hasCommands(relay);
            } else {
                User user = User.getUserByUserId(userId);

                if (user == null) {
                    throw new RestException(HttpServletResponse.SC_FORBIDDEN, RestException.NO_SUCH_USER,
                            "Invalid user access to location");
                }
                String locationId = req.getParameter("locationId");
                Collection<ControllerRelay> relays;

                if (locationId == null) {
                    relays = new ArrayList<ControllerRelay>();
                    for (Location location : user.getLocations()) {
                        relays.addAll(ControllerRelay.findRelaysInLocation(location));
                    }
                } else {
                    boolean mine = false;

                    for (String lid : user.getLocationIds()) {
                        if (lid.equals(locationId)) {
                            mine = true;
                            break;
                        }
                    }
                    Location location = Location.getLocation(locationId);

                    if (location == null || (!mine && !userId.equals(location.getOwnerId()))) {
                        throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_PARAMETER,
                                "No such location: " + locationId);
                    }
                    relays = ControllerRelay.findRelaysInLocation(location);
                }
                for (ControllerRelay relay : relays) {
                    for (PendingCommand cmd : PendingCommand.getCommands(relay)) {
                        list.add(toJSON(cmd));
                    }
                }
            }
            if (hasCommands != null) {
                resp.setHeader("x-imaginary-has-commands", String.valueOf(hasCommands));
            }
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.getWriter().println((new JSONArray(list)).toString());
            resp.getWriter().flush();
        } catch (PersistenceException e) {
            throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, RestException.INTERNAL_ERROR,
                    e.getMessage());
        }
    }

    @Override
    public void put(@Nonnull String requestId, @Nullable String userId, @Nonnull String[] path,
            @Nonnull HttpServletRequest req, @Nonnull HttpServletResponse resp,
            @Nonnull Map<String, Object> headers, @Nonnull Map<String, Object> parameters)
            throws RestException, IOException {
        if (userId != null) {
            throw new RestException(HttpServletResponse.SC_FORBIDDEN, RestException.USER_NOT_ALLOWED,
                    "A user cannot update a command state");
        }
        String commandId = (path.length > 1 ? path[1] : null);

        if (commandId == null) {
            throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_OPERATION,
                    "You cannot PUT against the command root");
        }
        try {
            PendingCommand cmd = PendingCommand.getCommand(commandId);

            if (cmd == null) {
                throw new RestException(HttpServletResponse.SC_NOT_FOUND, RestException.NO_SUCH_OBJECT,
                        "No such command: " + commandId);
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream()));
            StringBuilder source = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                source.append(line);
                source.append(" ");
            }
            JSONObject object = new JSONObject(source.toString());
            String action;

            if (object.has("action") && !object.isNull("action")) {
                action = object.getString("action");
            } else {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_ACTION,
                        "An invalid action was specified (or not specified) in the PUT");
            }
            if (action.equals("complete")) {
                object = object.getJSONObject("result");
                boolean result = (object.has("result") && object.getBoolean("result"));
                String errorMessage = (object.has("errorMessage") ? object.getString("errorMessage") : null);
                ControllerRelay relay = ControllerRelay.getRelay(cmd.getRelayId());

                cmd.update(PendingCommandState.EXECUTED, result, errorMessage);

                if (relay != null) {
                    resp.setHeader("x-imaginary-has-commands", String.valueOf(PendingCommand.hasCommands(relay)));
                }
                resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
            } else {
                throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_ACTION,
                        "The action " + action + " is not a valid action.");
            }
        } catch (JSONException e) {
            throw new RestException(HttpServletResponse.SC_BAD_REQUEST, RestException.INVALID_JSON,
                    "Invalid JSON in request");
        } catch (PersistenceException e) {
            throw new RestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, RestException.INTERNAL_ERROR,
                    e.getMessage());
        }

    }
}