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}