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