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.service.swagger.internal;
021
022import java.util.Collection;
023import java.util.List;
024import java.util.function.Predicate;
025import java.util.stream.Collectors;
026import org.apache.isis.applib.services.swagger.SwaggerService;
027import org.apache.isis.commons.collections.Can;
028import org.apache.isis.commons.collections.ImmutableEnumSet;
029import org.apache.isis.commons.internal.base._Casts;
030import org.apache.isis.commons.internal.exceptions._Exceptions;
031import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
032import org.apache.isis.core.metamodel.spec.ActionType;
033import org.apache.isis.core.metamodel.spec.ObjectSpecification;
034import org.apache.isis.core.metamodel.spec.feature.Contributed;
035import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
036import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
037import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
038import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
039import io.swagger.models.Response;
040
041public final class Util {
042    private Util() {
043    }
044
045    static boolean isVisibleForPublic(final ObjectAction objectAction) {
046        final ObjectSpecification specification = objectAction.getReturnType();
047        return (isVisibleForPublic(specification) || isTypeOfVisibleForPublic(objectAction)) && isVisibleForPublic(objectAction.getParameterTypes());
048    }
049
050    private static boolean isTypeOfVisibleForPublic(ObjectAction objectAction) {
051        final TypeOfFacet typeOfFacet = objectAction.getFacet(TypeOfFacet.class);
052        if (typeOfFacet == null) {
053            return false;
054        }
055        return isVisibleForPublic(typeOfFacet.valueSpec());
056    }
057
058    private static boolean isVisibleForPublic(Can<ObjectSpecification> parameterTypes) {
059        final boolean atLeastOneParamNotVisible = parameterTypes.stream().map(Util::isNotVisibleForPublic).findAny().isPresent();
060        return !atLeastOneParamNotVisible;
061    }
062
063    static boolean isVisibleForPublic(final ObjectAssociation objectAssociation) {
064        final ObjectSpecification specification = objectAssociation.getSpecification();
065        return isVisibleForPublic(specification);
066    }
067
068    static boolean isNotVisibleForPublic(final ObjectSpecification specification) {
069        return !isVisibleForPublic(specification);
070    }
071
072    static boolean isVisibleForPublic(final ObjectSpecification specification) {
073        if (specification == null) {
074            return true;
075        }
076        if (specification.isViewModel()) {
077            return true;
078        }
079        if (specification.isValue()) {
080            return true;
081        }
082        if (specification.isParentedOrFreeCollection()) {
083            TypeOfFacet typeOfFacet = specification.getFacet(TypeOfFacet.class);
084            if (typeOfFacet != null) {
085                ObjectSpecification elementSpec = typeOfFacet.valueSpec();
086                return isVisibleForPublic(elementSpec);
087            }
088        }
089        final Class<?> correspondingClass = specification.getCorrespondingClass();
090        return Collection.class.isAssignableFrom(correspondingClass) || correspondingClass.isArray() || correspondingClass == void.class || correspondingClass == Void.class;
091    }
092
093    static Predicate<ObjectAssociation> associationsWith(final SwaggerService.Visibility visibility) {
094        return new Predicate<ObjectAssociation>() {
095            @Override
096            public boolean test(final ObjectAssociation objectAssociation) {
097                return !visibility.isPublic() || isVisibleForPublic(objectAssociation);
098            }
099        };
100    }
101
102    static List<OneToOneAssociation> propertiesOf(final ObjectSpecification objectSpecification, final SwaggerService.Visibility visibility) {
103        return associationsOf(objectSpecification, ObjectAssociation.Predicates.PROPERTIES, visibility);
104    }
105
106    static List<OneToManyAssociation> collectionsOf(final ObjectSpecification objectSpecification, final SwaggerService.Visibility visibility) {
107        return associationsOf(objectSpecification, ObjectAssociation.Predicates.COLLECTIONS, visibility);
108    }
109
110    private static <T extends ObjectAssociation> List<T> associationsOf(final ObjectSpecification objectSpecification, final Predicate<ObjectAssociation> associationPredicate, final SwaggerService.Visibility visibility) {
111        final List<ObjectAssociation> list = objectSpecification.streamAssociations(Contributed.INCLUDED).filter(associationPredicate.and(associationsWith(visibility))).collect(Collectors.toList());
112        return _Casts.uncheckedCast(list);
113    }
114
115    static List<ObjectAction> actionsOf(final ObjectSpecification objectSpec, final SwaggerService.Visibility visibility, final ClassExcluder classExcluder) {
116        final org.apache.isis.commons.collections.ImmutableEnumSet<org.apache.isis.core.metamodel.spec.ActionType> actionTypes = actionTypesFor(visibility);
117        return objectSpec.streamObjectActions(actionTypes, Contributed.INCLUDED).filter(objectAction -> !classExcluder.exclude(objectAction) && !visibility.isPublic() || isVisibleForPublic(objectAction)).collect(Collectors.toList());
118    }
119
120    static String roSpec(final String section) {
121        return "RO Spec v1.0, section " + section;
122    }
123
124    static Response withCachingHeaders(final Response response, final Caching caching) {
125        caching.withHeaders(response);
126        return response;
127    }
128
129    static ImmutableEnumSet<ActionType> actionTypesFor(final SwaggerService.Visibility visibility) {
130        switch (visibility) {
131        case PUBLIC: 
132            return ActionType.USER_ONLY;
133        case PRIVATE: 
134            return ActionType.USER_ONLY;
135        case PRIVATE_WITH_PROTOTYPING: 
136            return ActionType.USER_AND_PROTOTYPE;
137        }
138        throw _Exceptions.unmatchedCase(visibility);
139    }
140}