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.domainobjects; 021 022import java.util.List; 023import java.util.Map; 024import java.util.Objects; 025import java.util.stream.Stream; 026import org.apache.isis.applib.annotation.Where; 027import org.apache.isis.commons.internal.collections._Lists; 028import org.apache.isis.core.metamodel.facets.collections.CollectionFacet; 029import org.apache.isis.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacet; 030import org.apache.isis.core.metamodel.interactions.managed.ManagedCollection; 031import org.apache.isis.core.metamodel.spec.ManagedObject; 032import org.apache.isis.core.metamodel.spec.ManagedObjects; 033import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation; 034import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; 035import org.apache.isis.viewer.restfulobjects.applib.Rel; 036import org.apache.isis.viewer.restfulobjects.applib.RepresentationType; 037import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext; 038import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder; 039import org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs; 040import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.CollectionDescriptionReprRenderer; 041 042public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRenderer<ObjectCollectionReprRenderer, OneToManyAssociation> { 043 public ObjectCollectionReprRenderer(final IResourceContext resourceContext, final LinkFollowSpecs linkFollowSpecs, final String collectionId, final JsonRepresentation representation) { 044 super(resourceContext, linkFollowSpecs, collectionId, RepresentationType.OBJECT_COLLECTION, representation, Where.PARENTED_TABLES); 045 } 046 047 @Override 048 public JsonRepresentation render() { 049 if (representation == null) { 050 return null; 051 } 052 renderMemberContent(); 053 final LinkFollowSpecs followValue = getLinkFollowSpecs().follow("value"); 054 boolean eagerlyRender = resourceContext.honorUiHints() && renderEagerly() || !followValue.isTerminated(); 055 if ((mode.isInline() && eagerlyRender) || mode.isStandalone() || mode.isMutated() || mode.isEventSerialization() || !ManagedObjects.isIdentifiable(objectAdapter)) { 056 addValue(followValue); 057 } 058 if (!mode.isEventSerialization()) { 059 putDisabledReasonIfDisabled(); 060 } 061 if (mode.isStandalone() || mode.isMutated()) { 062 addExtensionsIsisProprietaryChangedObjects(); 063 } 064 return representation; 065 } 066 067 private boolean renderEagerly() { 068 final DefaultViewFacet defaultViewFacet = objectMember.getFacet(DefaultViewFacet.class); 069 return defaultViewFacet != null && Objects.equals(defaultViewFacet.value(), "table"); 070 } 071 072 // /////////////////////////////////////////////////// 073 // value 074 // /////////////////////////////////////////////////// 075 private void addValue(final LinkFollowSpecs linkFollower) { 076 final org.apache.isis.core.metamodel.spec.ManagedObject valueAdapter = objectMember.get(objectAdapter, getInteractionInitiatedBy()); 077 if (valueAdapter == null) { 078 return; 079 } 080 final LinkFollowSpecs followHref = linkFollower.follow("href"); 081 boolean eagerlyRender = resourceContext.honorUiHints() && renderEagerly(valueAdapter) || !followHref.isTerminated(); 082 final Stream<ManagedObject> elementAdapters = CollectionFacet.streamAdapters(valueAdapter); 083 final List<JsonRepresentation> list = _Lists.newArrayList(); 084 elementAdapters.forEach(elementAdapter -> { 085 final LinkBuilder valueLinkBuilder = DomainObjectReprRenderer.newLinkToBuilder(resourceContext, Rel.VALUE, elementAdapter); 086 if (eagerlyRender) { 087 final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getResourceContext(), followHref, JsonRepresentation.newMap()); 088 renderer.with(elementAdapter); 089 if (mode.isEventSerialization()) { 090 renderer.asEventSerialization(); 091 } 092 valueLinkBuilder.withValue(renderer.render()); 093 } 094 list.add(valueLinkBuilder.build()); 095 }); 096 representation.mapPut("value", list); 097 } 098 099 private boolean renderEagerly(ManagedObject valueAdapter) { 100 return renderEagerly() && resourceContext.canEagerlyRender(valueAdapter); 101 } 102 103 // /////////////////////////////////////////////////// 104 // details link 105 // /////////////////////////////////////////////////// 106 /** 107 * Mandatory hook method to support x-ro-follow-links 108 */ 109 @Override 110 protected void followDetailsLink(final JsonRepresentation detailsLink) { 111 final org.apache.isis.applib.annotation.Where where = resourceContext.getWhere(); 112 final JsonRepresentation representation = JsonRepresentation.newMap(); 113 final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(getResourceContext(), getLinkFollowSpecs(), null, representation); 114 renderer.with(ManagedCollection.of(objectAdapter, objectMember, where)).asFollowed(); 115 detailsLink.mapPut("value", renderer.render()); 116 } 117 118 // /////////////////////////////////////////////////// 119 // mutators 120 // /////////////////////////////////////////////////// 121 @Override 122 protected void addMutatorLinksIfEnabled() { 123 if (usability().isVetoed()) { 124 return; 125 } 126 final CollectionSemantics semantics = CollectionSemantics.determine(objectMember); 127 addMutatorLink(semantics.getAddToKey()); 128 addMutatorLink(semantics.getRemoveFromKey()); 129 return; 130 } 131 132 private void addMutatorLink(final String key) { 133 final Map<String, MutatorSpec> mutators = objectMemberType.getMutators(); 134 final MutatorSpec mutatorSpec = mutators.get(key); 135 addLinkFor(mutatorSpec); 136 } 137 138 // /////////////////////////////////////////////////// 139 // extensions and links 140 // /////////////////////////////////////////////////// 141 @Override 142 protected void addLinksToFormalDomainModel() { 143 if (resourceContext.suppressDescribedByLinks()) { 144 return; 145 } 146 final JsonRepresentation link = CollectionDescriptionReprRenderer.newLinkToBuilder(resourceContext, Rel.DESCRIBEDBY, objectAdapter.getSpecification(), objectMember).build(); 147 getLinks().arrayAdd(link); 148 } 149 150 @Override 151 protected void putExtensionsIsisProprietary() { 152 final CollectionSemantics semantics = CollectionSemantics.determine(objectMember); 153 getExtensions().mapPut("collectionSemantics", semantics.name().toLowerCase()); 154 } 155}