001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.isis.viewer.restfulobjects.rendering.service.conneg; 020 021import java.util.List; 022import java.util.Objects; 023 024import javax.ws.rs.core.MediaType; 025import javax.ws.rs.core.Response; 026import javax.xml.bind.annotation.XmlRootElement; 027 028import org.apache.isis.core.commons.internal.base._Strings; 029import org.apache.isis.core.commons.internal.collections._Lists; 030import org.apache.isis.core.commons.internal.factory.InstanceUtil; 031import org.apache.isis.core.metamodel.spec.ManagedObject; 032import org.apache.isis.viewer.restfulobjects.applib.RestfulResponse; 033import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext; 034import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException; 035import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndAction; 036import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndActionInvocation; 037import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndCollection; 038import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndProperty; 039 040public abstract class ContentNegotiationServiceAbstract implements ContentNegotiationService { 041 042 @Override 043 public Response.ResponseBuilder buildResponse( 044 final IResourceContext renderContext2, 045 final ManagedObject objectAdapter) { 046 return null; 047 } 048 049 @Override 050 public Response.ResponseBuilder buildResponse( 051 final IResourceContext renderContext2, 052 final ObjectAndProperty objectAndProperty) { 053 return null; 054 } 055 056 @Override 057 public Response.ResponseBuilder buildResponse( 058 final IResourceContext renderContext2, 059 final ObjectAndCollection objectAndCollection) { 060 return null; 061 } 062 063 @Override 064 public Response.ResponseBuilder buildResponse( 065 final IResourceContext renderContext2, 066 final ObjectAndAction objectAndAction) { 067 return null; 068 } 069 070 @Override 071 public Response.ResponseBuilder buildResponse( 072 final IResourceContext renderContext2, 073 final ObjectAndActionInvocation objectAndActionInvocation) { 074 return null; 075 } 076 077 // -- convenience methods for subclasses (possibly hooks) 078 079 /** 080 * Potential hook to allow a domain object to be mapped. 081 */ 082 protected Object objectOf(final ManagedObject objectAdapter) { 083 return objectAdapter.getPojo(); 084 } 085 086 protected Object returnedObjectOf(final ObjectAndActionInvocation objectAndActionInvocation) { 087 final ManagedObject returnedAdapter = objectAndActionInvocation.getReturnedAdapter(); 088 return objectOf(returnedAdapter); 089 } 090 091 protected Class<?> loadClass(final String cls) { 092 final Class<?> domainType; 093 try { 094 domainType = InstanceUtil.loadClass(cls); 095 }catch (final Exception ex) { 096 throw RestfulObjectsApplicationException.createWithCause(RestfulResponse.HttpStatusCode.BAD_REQUEST, ex); 097 } 098 099 return domainType; 100 } 101 102 protected void ensureJaxbAnnotated(final Class<?> domainType) { 103 if(domainType.getAnnotation(XmlRootElement.class) == null) { 104 throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.BAD_REQUEST, "Requested domain Type '" + domainType.getName() + "' is not annotated with JAXB @XmlRootElement annotation"); 105 } 106 } 107 108 protected void ensureDomainObjectAssignable(final String xRoDomainType, final Class<?> domainType, final Object domainObject) { 109 if(!domainType.isAssignableFrom(domainObject.getClass())) { 110 throw RestfulObjectsApplicationException.createWithMessage( 111 RestfulResponse.HttpStatusCode.NOT_ACCEPTABLE, 112 "Requested object of type '%s' however the object returned by the domain object is not assignable (is '%s')", 113 xRoDomainType, domainObject.getClass().getName()); 114 } 115 } 116 117 protected boolean mediaTypeParameterMatches( 118 final List<MediaType> acceptableMediaTypes, 119 final String parameter, final String parameterValue) { 120 for (MediaType mediaType : acceptableMediaTypes) { 121 final String paramValue = sanitize(mediaType.getParameters().get(parameter)); 122 if (Objects.equals(paramValue, parameterValue)) { 123 return true; 124 } 125 } 126 return false; 127 } 128 129 protected List<String> mediaTypeParameterList( 130 final List<MediaType> acceptableMediaTypes, 131 final String parameter) { 132 final List<String> paramList = _Lists.newArrayList(); 133 for (MediaType mediaType : acceptableMediaTypes) { 134 final String paramValue = sanitize(mediaType.getParameters().get(parameter)); 135 _Strings.splitThenStream(paramValue, ",") 136 .map(String::trim) 137 .forEach(paramList::add); 138 } 139 return paramList; 140 } 141 142 143 /** 144 * Remove any single quotes. 145 */ 146 private String sanitize(String mediaParam) { 147 if (mediaParam == null) { 148 return null; 149 } 150 mediaParam = mediaParam.trim(); 151 if(mediaParam.startsWith("'")) { 152 mediaParam = mediaParam.substring(1); 153 } 154 if(mediaParam.endsWith("'")) { 155 mediaParam = mediaParam.substring(0, mediaParam.length()-1); 156 } 157 return mediaParam; 158 } 159 160}