All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.centurylink.mdw.services.rest.JsonRestService Maven / Gradle / Ivy

There is a newer version: 6.1.39
Show newest version
/*
 * Copyright (C) 2017 CenturyLink, Inc.
 *
 * 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.centurylink.mdw.services.rest;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;

import com.centurylink.mdw.common.service.Query;
import com.centurylink.mdw.model.workflow.Process;
import com.centurylink.mdw.service.data.process.ProcessCache;
import org.json.JSONException;
import org.json.JSONObject;

import com.centurylink.mdw.cache.asset.PackageCache;
import com.centurylink.mdw.common.service.JsonService;
import com.centurylink.mdw.common.service.ServiceException;
import com.centurylink.mdw.config.PropertyManager;
import com.centurylink.mdw.constant.OwnerType;
import com.centurylink.mdw.model.JsonArray;
import com.centurylink.mdw.model.JsonExport;
import com.centurylink.mdw.model.JsonExportable;
import com.centurylink.mdw.model.JsonObject;
import com.centurylink.mdw.model.Jsonable;
import com.centurylink.mdw.model.Status;
import com.centurylink.mdw.model.StatusResponse;
import com.centurylink.mdw.model.listener.Listener;
import com.centurylink.mdw.model.user.User;
import com.centurylink.mdw.services.ServiceLocator;
import com.centurylink.mdw.services.WorkflowServices;
import com.centurylink.mdw.util.JsonUtil;

import io.swagger.annotations.Api;

public abstract class JsonRestService extends RestService implements JsonService {

    public String getJson(JSONObject json, Map headers) throws ServiceException {
        String path = headers.get(Listener.METAINFO_REQUEST_PATH);
        if (path.startsWith("/api/") && !isApi())
            throw new ServiceException(Status.NOT_FOUND);
        try {
            JSONObject response;
            User user = authorize(path, json, headers);
            response = service(path, json, headers);
            if (user != null)
                auditLog(getUserAction(user, path, json, headers));
            if (response == null) {
                return getDefaultResponse(headers).toString(2);
            }
            else if (response.has(JsonArray.GENERIC_ARRAY)) {
                return response.getJSONArray(JsonArray.GENERIC_ARRAY).toString(2);
            }
            else {
                if (response.has("status")) {
                    String code = headers.get(Listener.METAINFO_HTTP_STATUS_CODE);
                    if (code == null || code.equals("0")) {
                        JSONObject status = response.optJSONObject("status");
                        if (status != null && status.has("code")) {
                            int setCode = status.optInt("code");
                            if (setCode != 0)
                                headers.put(Listener.METAINFO_HTTP_STATUS_CODE, String.valueOf(setCode));
                        }

                    }
                }
                return response.toString(2);
            }
        }
        catch (JSONException ex) {
            throw new ServiceException(ex.getMessage(), ex);
        }
    }

    protected JSONObject service(String path, JSONObject content, Map headers) throws ServiceException, JSONException {
        String method = headers.get(Listener.METAINFO_HTTP_METHOD);
        if ("GET".equals(method))
            return get(path, headers);
        else if ("DELETE".equals(method))
            return delete(path, content, headers);
        else if (content == null) // content couldn't be parsed
            throw new ServiceException(ServiceException.BAD_REQUEST, "Malformed JSON in request body");

        if ("POST".equals(method))
            return post(path, content, headers);
        else if ("PUT".equals(method))
            return put(path, content, headers);
        else if ("PATCH".equals(method))
            return patch(path, content, headers);
        else
            throw new ServiceException(ServiceException.NOT_ALLOWED, method + " not implemented");
    }

    /**
     * Retrieve an existing entity or relationship.
     */
    @GET
    public JSONObject get(String path, Map headers) throws ServiceException, JSONException {
        throw new ServiceException(ServiceException.NOT_ALLOWED, "GET not implemented");
    }

    /**
     * Create a new entity or relationship.
     * Or perform other action requests that cannot be categorized into put or delete.
     */
    @POST
    public JSONObject post(String path, JSONObject content, Map headers) throws ServiceException, JSONException {
        throw new ServiceException(ServiceException.NOT_ALLOWED, "POST not implemented");
    }

    /**
     * Update an existing entity with different data.
     */
    @PUT
    public JSONObject put(String path, JSONObject content, Map headers) throws ServiceException, JSONException {
        throw new ServiceException(ServiceException.NOT_ALLOWED, "PUT not implemented");
    }

    /**
     * Delete an existing entity or relationship.
     */
    @DELETE
    public JSONObject delete(String path, JSONObject content, Map headers) throws ServiceException, JSONException {
        throw new ServiceException(ServiceException.NOT_ALLOWED, "DELETE not implemented");
    }

    /**
     * Incrementally update an existing entity.
     */
    @PUT
    public JSONObject patch(String path, JSONObject content, Map headers) throws ServiceException, JSONException {
        throw new ServiceException(ServiceException.NOT_ALLOWED, "PATCH not implemented");
    }

    public String getText(Object requestObj, Map metaInfo) throws ServiceException {
        throw new ServiceException(ServiceException.BAD_REQUEST, metaInfo.get(Listener.METAINFO_REQUEST_PATH) + " requires JSON content type");
    }

    @Override
    protected void validateResponse(String response) throws ServiceException {
        try {
            JSONObject jsonObject = new JsonObject(response);
            JSONObject status = jsonObject.getJSONObject("status");
            int code = status.getInt("code");
            String message = status.getString("message");
            if (code >= 400)
                throw new ServiceException(code, "Propagation error: " + message);
        }
        catch (JSONException ex) {
            throw new ServiceException(ex.getMessage(), ex);
        }
    }

    protected JsonExport getExporter(Map headers) throws JSONException, ServiceException {
        String method = headers.get(Listener.METAINFO_HTTP_METHOD);
        if ("GET".equals(method)) {
            if (this instanceof JsonExportable) {
                authorizeExport(headers);
                // TODO headers.put("max", String.valueOf(Query.MAX_ALL));
                String path = headers.get(Listener.METAINFO_REQUEST_PATH);
                JSONObject response = service(path, null, headers);
                JsonExportable exportable = (JsonExportable)this;
                Query query = getQuery(path, headers);
                Jsonable jsonable = exportable.toExportJson(query, response);
                String name = exportable.getExportName();
                JSONObject filters = exportable.getExportFilters(query);
                return new JsonExport(jsonable, name, filters);
            }
            else {
                throw new ServiceException(HTTP_404_NOT_FOUND, "Service not exportable");
            }
        }
        else {
            throw new ServiceException(HTTP_405_METHOD_NOT_ALLOWED, "Unsupported method: " + method);
        }
    }

    /**
     * Binary content must be Base64 encoded for API compatibility.
     */
    public String export(String downloadFormat, Map headers) throws ServiceException {
        try {
            JsonExport exporter = getExporter(headers);
            if (Listener.DOWNLOAD_FORMAT_EXCEL.equals(downloadFormat))
                return exporter.exportXlsxBase64();
            else if (Listener.DOWNLOAD_FORMAT_ZIP.equals(downloadFormat))
                return exporter.exportZipBase64();
            else
                throw new ServiceException(HTTP_400_BAD_REQUEST, "Unsupported download format: " + downloadFormat);
        }
        catch (ServiceException ex) {
            throw ex;
        }
        catch (Exception ex) {
            throw new ServiceException(HTTP_500_INTERNAL_ERROR, ex.getMessage(), ex);
        }
    }

    /**
     * Helper method for invoking a service process.  Populates response headers from variable value.
     */
    protected JSONObject invokeServiceProcess(String name, Object request, String requestId,
            Map parameters, Map headers) throws ServiceException {
        JSONObject responseJson;
        Map responseHeaders = new HashMap<>();
        Object responseObject = ServiceLocator.getWorkflowServices().invokeProcess(name,
                request, requestId, parameters, headers, responseHeaders).getObject();
        if (responseObject instanceof JSONObject)
            responseJson = (JSONObject) responseObject;
        else if (responseObject instanceof Jsonable)
            responseJson = ((Jsonable) responseObject).getJson();
        else
            throw new ServiceException(HTTP_500_INTERNAL_ERROR,
                    "Unsupported response type: " + (responseObject == null ? null : responseObject.getClass()));
        for (String key : responseHeaders.keySet())
            headers.put(key, responseHeaders.get(key));
        return responseJson;
    }

    protected void launchProcess(String name, String masterRequestId,
            Map parameters, Map headers) throws ServiceException {
        WorkflowServices workflowServices = ServiceLocator.getWorkflowServices();
        long documentId = Long.parseLong(headers.get(Listener.METAINFO_DOCUMENT_ID));
        // for convenience, populate requestHeaders var if present since not service
        if (!parameters.containsKey("requestHeaders")) {
            Process process = ProcessCache.getProcess(name);
            if (process.getVariable("requestHeaders") != null)
                parameters.put("requestHeaders", headers);
        }
        workflowServices.startProcess(name, masterRequestId, OwnerType.DOCUMENT, documentId, parameters);
    }

    protected int notifyProcess(String packageName, String eventId, Map headers) throws ServiceException {
        WorkflowServices workflowServices = ServiceLocator.getWorkflowServices();
        return workflowServices.notify(PackageCache.getPackage(packageName), eventId, JsonUtil.getJson(headers));
    }

    protected int notifyProcess(String packageName, String eventId, String eventMessage) throws ServiceException {
        WorkflowServices workflowServices = ServiceLocator.getWorkflowServices();
        return workflowServices.notify(PackageCache.getPackage(packageName), eventId, eventMessage);
    }

    /**
     * True if should expose via the /api/* path.  This path indicates public consumption,
     * versus /services/*, which is not included in swaggers and meant for internal use.
     */
    public boolean isApi() {
        return this.getClass().getAnnotation(Api.class) != null;
    }

    protected JSONObject getDefaultResponse(Map headers) {
        if ("true".equals(PropertyManager.getProperty("mdw.service.default.response.compat"))) {
            return null; // compatibility for any previous users who depend on old status code of 0
        }
        String code = headers.get(Listener.METAINFO_HTTP_STATUS_CODE);
        if (code != null) {
            return StatusResponse.forCode(Integer.parseInt(code)).getJson();
        }
        else {
            return new StatusResponse(Status.OK).getJson();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy