001// Generated by delombok at Mon Oct 12 22:51:05 BST 2020 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020package org.apache.isis.viewer.restfulobjects.rendering; 021 022import java.util.List; 023import java.util.Map; 024import java.util.stream.Stream; 025import javax.ws.rs.core.MediaType; 026import org.apache.isis.commons.internal.collections._Lists; 027import org.apache.isis.commons.internal.collections._Maps; 028import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; 029import org.apache.isis.core.metamodel.spec.ManagedObject; 030import org.apache.isis.core.metamodel.spec.ObjectSpecification; 031import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; 032import org.apache.isis.viewer.restfulobjects.applib.Rel; 033import org.apache.isis.viewer.restfulobjects.applib.RepresentationType; 034import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.DomainObjectReprRenderer; 035import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.JsonValueEncoder; 036import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.DomainTypeReprRenderer; 037 038public abstract class ReprRendererAbstract<R extends ReprRendererAbstract<R, T>, T> implements ReprRenderer<R, T> { 039 protected final IResourceContext resourceContext; 040 protected final JsonValueEncoder jsonValueEncoder; 041 private final LinkFollowSpecs linkFollower; 042 private final RepresentationType representationType; 043 protected final JsonRepresentation representation; 044 private final Map<String, String> mediaTypeParams = _Maps.newLinkedHashMap(); 045 private final InteractionInitiatedBy interactionInitiatedBy; 046 protected boolean includesSelf; 047 048 public ReprRendererAbstract(final IResourceContext resourceContext, final LinkFollowSpecs linkFollower, final RepresentationType representationType, final JsonRepresentation representation) { 049 this.resourceContext = resourceContext; 050 this.jsonValueEncoder = resourceContext.getServiceRegistry().lookupServiceElseFail(JsonValueEncoder.class); 051 this.linkFollower = asProvidedElseCreate(linkFollower); 052 this.representationType = representationType; 053 this.representation = representation; 054 this.interactionInitiatedBy = determineInteractionInitiatedByFrom(this.resourceContext); 055 } 056 057 private static InteractionInitiatedBy determineInteractionInitiatedByFrom(final IResourceContext resourceContext) { 058 return resourceContext.getInteractionInitiatedBy(); 059 } 060 061 protected InteractionInitiatedBy getInteractionInitiatedBy() { 062 return interactionInitiatedBy; 063 } 064 065 public LinkFollowSpecs getLinkFollowSpecs() { 066 return linkFollower; 067 } 068 069 private LinkFollowSpecs asProvidedElseCreate(final LinkFollowSpecs linkFollower) { 070 if (linkFollower != null) { 071 return linkFollower; 072 } 073 return LinkFollowSpecs.create(resourceContext.getFollowLinks()); 074 } 075 076 @Override 077 public MediaType getMediaType() { 078 return representationType.getJsonMediaType(mediaTypeParams); 079 } 080 081 protected void addMediaTypeParams(String param, String paramValue) { 082 mediaTypeParams.put(param, paramValue); 083 } 084 085 @SuppressWarnings("unchecked") 086 public R includesSelf() { 087 this.includesSelf = true; 088 return (R) this; 089 } 090 091 public R withLink(final Rel rel, final String href) { 092 if (href != null) { 093 getLinks().arrayAdd(LinkBuilder.newBuilder(resourceContext, rel.getName(), representationType, href).build()); 094 } 095 return cast(this); 096 } 097 098 public R withLink(final Rel rel, final JsonRepresentation link) { 099 final String relStr = link.getString("rel"); 100 if (relStr == null || !relStr.equals(rel.getName())) { 101 throw new IllegalArgumentException("Provided link does not have a \'rel\' of \'" + rel.getName() + "\'; was: " + link); 102 } 103 if (link != null) { 104 getLinks().arrayAdd(link); 105 } 106 return cast(this); 107 } 108 109 /** 110 * Will lazily create links array as required 111 */ 112 protected JsonRepresentation getLinks() { 113 JsonRepresentation links = representation.getArray("links"); 114 if (links == null) { 115 links = JsonRepresentation.newArray(); 116 representation.mapPut("links", links); 117 } 118 return links; 119 } 120 121 protected void addLink(final Rel rel, final ObjectSpecification objectSpec) { 122 if (objectSpec == null) { 123 return; 124 } 125 final LinkBuilder linkBuilder = DomainTypeReprRenderer.newLinkToBuilder(getResourceContext(), rel, objectSpec); 126 JsonRepresentation link = linkBuilder.build(); 127 getLinks().arrayAdd(link); 128 final LinkFollowSpecs linkFollower = getLinkFollowSpecs().follow("links"); 129 if (linkFollower.matches(link)) { 130 final DomainTypeReprRenderer renderer = new DomainTypeReprRenderer(getResourceContext(), linkFollower, JsonRepresentation.newMap()).with(objectSpec); 131 link.mapPut("value", renderer.render()); 132 } 133 } 134 135 /** 136 * Will lazily create extensions map as required 137 */ 138 protected JsonRepresentation getExtensions() { 139 JsonRepresentation extensions = representation.getMap("extensions"); 140 if (extensions == null) { 141 extensions = JsonRepresentation.newMap(); 142 representation.mapPut("extensions", extensions); 143 } 144 return extensions; 145 } 146 147 public R withExtensions(final JsonRepresentation extensions) { 148 if (!extensions.isMap()) { 149 throw new IllegalArgumentException("extensions must be a map"); 150 } 151 representation.mapPut("extensions", extensions); 152 return cast(this); 153 } 154 155 @SuppressWarnings("unchecked") 156 protected static <R extends ReprRendererAbstract<R, T>, T> R cast(final ReprRendererAbstract<R, T> builder) { 157 return (R) builder; 158 } 159 160 @Override 161 public abstract JsonRepresentation render(); 162 163 /** 164 * Convenience for representations that are returned from objects that 165 166 * mutate state. 167 */ 168 protected final void addExtensionsIsisProprietaryChangedObjects() { 169 // TODO: have removed UpdateNotifier, plan is to re-introduce using the IsisTransaction 170 // enlisted objects (which would also allow newly-created objects to be shown) 171 final List<ManagedObject> changedObjects = _Lists.newArrayList(); // updateNotifier.getChangedObjects(); 172 final List<ManagedObject> disposedObjects = _Lists.newArrayList(); // updateNotifier.getDisposedObjects(); 173 addToExtensions("changed", changedObjects); 174 addToExtensions("disposed", disposedObjects); 175 } 176 177 private void addToExtensions(final String key, final List<ManagedObject> adapters) { 178 if (adapters == null || adapters.isEmpty()) { 179 return; 180 } 181 final JsonRepresentation adapterList = JsonRepresentation.newArray(); 182 getExtensions().mapPut(key, adapterList); 183 for (final org.apache.isis.core.metamodel.spec.ManagedObject adapter : adapters) { 184 adapterList.arrayAdd(DomainObjectReprRenderer.newLinkToBuilder(getResourceContext(), Rel.VALUE, adapter).build()); 185 } 186 } 187 188 protected Stream<ManagedObject> streamServiceAdapters() { 189 final org.apache.isis.core.metamodel.context.MetaModelContext metaModelContext = resourceContext.getMetaModelContext(); 190 return metaModelContext.streamServiceAdapters(); 191 } 192 193 @java.lang.SuppressWarnings("all") 194 public IResourceContext getResourceContext() { 195 return this.resourceContext; 196 } 197 198 @java.lang.SuppressWarnings("all") 199 public JsonValueEncoder getJsonValueEncoder() { 200 return this.jsonValueEncoder; 201 } 202}