001/**
002 *  Licensed to the Apache Software Foundation (ASF) under one or more
003 *  contributor license agreements.  See the NOTICE file distributed with
004 *  this work for additional information regarding copyright ownership.
005 *  The ASF licenses this file to You under the Apache License, Version 2.0
006 *  (the "License"); you may not use this file except in compliance with
007 *  the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS,
013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 *  See the License for the specific language governing permissions and
015 *  limitations under the License.
016 */
017package org.apache.isis.viewer.restfulobjects.server.resources;
018
019import java.io.InputStream;
020import java.util.List;
021
022import javax.ws.rs.Consumes;
023import javax.ws.rs.GET;
024import javax.ws.rs.POST;
025import javax.ws.rs.PUT;
026import javax.ws.rs.Path;
027import javax.ws.rs.PathParam;
028import javax.ws.rs.Produces;
029import javax.ws.rs.QueryParam;
030import javax.ws.rs.core.MediaType;
031import javax.ws.rs.core.Response;
032
033import org.apache.isis.applib.annotation.Where;
034import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
035import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
036import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
037import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
038import org.apache.isis.viewer.restfulobjects.applib.client.RestfulRequest.DomainModel;
039import org.apache.isis.viewer.restfulobjects.applib.client.RestfulRequest.RequestParameter;
040import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
041import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource;
042import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainObjectReprRenderer;
043import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainServiceLinkTo;
044import org.apache.isis.viewer.restfulobjects.server.resources.DomainResourceHelper.MemberMode;
045
046@Path("/services")
047public class DomainServiceResourceServerside extends ResourceAbstract implements DomainServiceResource {
048
049    @Override
050    @GET
051    @Path("/")
052    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_LIST, RestfulMediaType.APPLICATION_JSON_ERROR })
053    public Response services() {
054        init(RepresentationType.LIST, Where.STANDALONE_TABLES);
055
056        final List<ObjectAdapter> serviceAdapters = getResourceContext().getServiceAdapters();
057
058        final DomainServicesListReprRenderer renderer = new DomainServicesListReprRenderer(getResourceContext(), null, JsonRepresentation.newMap());
059        renderer.usingLinkToBuilder(new DomainServiceLinkTo())
060            .includesSelf()
061            .with(serviceAdapters);
062
063        return responseOfOk(renderer, Caching.ONE_DAY).build();
064    }
065
066    // //////////////////////////////////////////////////////////
067    // domain service
068    // //////////////////////////////////////////////////////////
069
070    @Override
071    @GET
072    @Path("/{serviceId}")
073    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_OBJECT, RestfulMediaType.APPLICATION_JSON_ERROR })
074    public Response service(@PathParam("serviceId") final String serviceId) {
075        init(RepresentationType.DOMAIN_OBJECT, Where.OBJECT_FORMS);
076
077        final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
078
079        final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getResourceContext(), null, JsonRepresentation.newMap());
080        renderer.usingLinkToBuilder(new DomainServiceLinkTo())
081            .with(serviceAdapter)
082            .includesSelf();
083
084        return responseOfOk(renderer, Caching.ONE_DAY).build();
085    }
086
087    // //////////////////////////////////////////////////////////
088    // domain service property
089    // //////////////////////////////////////////////////////////
090
091    @Override
092    @GET
093    @Path("/{serviceId}/properties/{propertyId}")
094    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_OBJECT_PROPERTY, RestfulMediaType.APPLICATION_JSON_ERROR })
095    public Response propertyDetails(@PathParam("serviceId") final String serviceId, @PathParam("propertyId") final String propertyId) {
096        init(RepresentationType.OBJECT_PROPERTY, Where.OBJECT_FORMS);
097
098        final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
099        final DomainResourceHelper helper = new DomainResourceHelper(getResourceContext(), serviceAdapter).using(new DomainServiceLinkTo());
100
101        return helper.propertyDetails(propertyId, MemberMode.NOT_MUTATING, Caching.ONE_DAY, getResourceContext().getWhere());
102    }
103
104    // //////////////////////////////////////////////////////////
105    // domain service action
106    // //////////////////////////////////////////////////////////
107
108    @Override
109    @GET
110    @Path("/{serviceId}/actions/{actionId}")
111    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_OBJECT_ACTION, RestfulMediaType.APPLICATION_JSON_ERROR })
112    public Response actionPrompt(@PathParam("serviceId") final String serviceId, @PathParam("actionId") final String actionId) {
113        init(RepresentationType.OBJECT_ACTION, Where.OBJECT_FORMS);
114
115        final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
116        final DomainResourceHelper helper = new DomainResourceHelper(getResourceContext(), serviceAdapter).using(new DomainServiceLinkTo());
117
118        return helper.actionPrompt(actionId, getResourceContext().getWhere());
119    }
120
121    // //////////////////////////////////////////////////////////
122    // domain service action invoke
123    // //////////////////////////////////////////////////////////
124
125    @Override
126    @GET
127    @Path("/{serviceId}/actions/{actionId}/invoke")
128    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_ACTION_RESULT, RestfulMediaType.APPLICATION_JSON_ERROR })
129    public Response invokeActionQueryOnly(@PathParam("serviceId") final String serviceId, @PathParam("actionId") final String actionId, @QueryParam("x-isis-querystring") final String xIsisQueryString) {
130        init(RepresentationType.ACTION_RESULT, Where.STANDALONE_TABLES, xIsisQueryString);
131
132        final JsonRepresentation arguments = getResourceContext().getQueryStringAsJsonRepr();
133        
134        final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
135        final DomainResourceHelper helper = new DomainResourceHelper(getResourceContext(), serviceAdapter).using(new DomainServiceLinkTo());
136
137        return helper.invokeActionQueryOnly(actionId, arguments, getResourceContext().getWhere());
138    }
139
140
141    @Override
142    @PUT
143    @Path("/{serviceId}/actions/{actionId}/invoke")
144    @Consumes({ MediaType.WILDCARD })
145    // to save the client having to specify a Content-Type: application/json
146    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_ACTION_RESULT, RestfulMediaType.APPLICATION_JSON_ERROR })
147    public Response invokeActionIdempotent(@PathParam("serviceId") final String serviceId, @PathParam("actionId") final String actionId, final InputStream body) {
148        init(RepresentationType.ACTION_RESULT, Where.STANDALONE_TABLES, body);
149
150        final JsonRepresentation arguments = getResourceContext().getQueryStringAsJsonRepr();
151        
152        final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
153        final DomainResourceHelper helper = new DomainResourceHelper(getResourceContext(), serviceAdapter).using(new DomainServiceLinkTo());
154
155        return helper.invokeActionIdempotent(actionId, arguments, getResourceContext().getWhere());
156    }
157
158
159    @Override
160    @POST
161    @Path("/{serviceId}/actions/{actionId}/invoke")
162    @Consumes({ MediaType.WILDCARD })
163    // to save the client having to specify a Content-Type: application/json
164    @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_ACTION_RESULT, RestfulMediaType.APPLICATION_JSON_ERROR })
165    public Response invokeAction(@PathParam("serviceId") final String serviceId, @PathParam("actionId") final String actionId, final InputStream body) {
166        init(RepresentationType.ACTION_RESULT, Where.STANDALONE_TABLES, body);
167
168        final JsonRepresentation arguments = getResourceContext().getQueryStringAsJsonRepr();
169        
170        final ObjectAdapter serviceAdapter = getServiceAdapter(serviceId);
171        final DomainResourceHelper helper = new DomainResourceHelper(getResourceContext(), serviceAdapter).using(new DomainServiceLinkTo());
172
173        return helper.invokeAction(actionId, arguments, getResourceContext().getWhere());
174    }
175
176}