/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.isis.core.metamodel.services.swagger.internal;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.isis.applib.filter.Filter;
import org.apache.isis.applib.filter.Filters;
import org.apache.isis.applib.services.swagger.SwaggerService;
import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.spec.ActionType;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import io.swagger.models.Response;
public final class Util {
private Util(){}
static boolean isVisibleForPublic(final ObjectAction objectAction) {
final ObjectSpecification specification = objectAction.getReturnType();
boolean visible = isVisibleForPublic(specification);
if(!visible) {
final TypeOfFacet typeOfFacet = objectAction.getFacet(TypeOfFacet.class);
if(typeOfFacet != null) {
ObjectSpecification elementSpec = typeOfFacet.valueSpec();
if(!isVisibleForPublic(elementSpec)) {
return false;
}
}
}
List<ObjectSpecification> parameterTypes = objectAction.getParameterTypes();
for (ObjectSpecification parameterType : parameterTypes) {
boolean paramVisible = isVisibleForPublic(parameterType);
if(!paramVisible) {
return false;
}
}
return true;
}
static boolean isVisibleForPublic(final ObjectAssociation objectAssociation) {
final ObjectSpecification specification = objectAssociation.getSpecification();
return isVisibleForPublic(specification);
}
static boolean isVisibleForPublic(final ObjectSpecification specification) {
if (specification == null) {
return true;
}
if(specification.isViewModel()) {
return true;
}
if(specification.isValue()) {
return true;
}
if(specification.isParentedOrFreeCollection()) {
TypeOfFacet typeOfFacet = specification.getFacet(TypeOfFacet.class);
if(typeOfFacet != null) {
ObjectSpecification elementSpec = typeOfFacet.valueSpec();
return isVisibleForPublic(elementSpec);
}
}
final Class<?> correspondingClass = specification.getCorrespondingClass();
return Collection.class.isAssignableFrom(correspondingClass) ||
correspondingClass.isArray() ||
correspondingClass == void.class ||
correspondingClass == Void.class;
}
static Filter<ObjectAssociation> associationsWith(final SwaggerService.Visibility visibility) {
return new Filter<ObjectAssociation>() {
@Override
public boolean accept(final ObjectAssociation objectAssociation) {
return !visibility.isPublic() || isVisibleForPublic(objectAssociation);
}
};
}
static List<OneToOneAssociation> propertiesOf(
final ObjectSpecification objectSpecification,
final SwaggerService.Visibility visibility) {
return associationsOf(objectSpecification, ObjectAssociation.Filters.PROPERTIES, visibility);
}
static List<OneToManyAssociation> collectionsOf(
final ObjectSpecification objectSpecification,
final SwaggerService.Visibility visibility) {
return associationsOf(objectSpecification, ObjectAssociation.Filters.COLLECTIONS, visibility);
}
static <T extends ObjectAssociation> List<T> associationsOf(
final ObjectSpecification objectSpecification,
final Filter<ObjectAssociation> associationFilter, final SwaggerService.Visibility visibility) {
@SuppressWarnings("rawtypes")
final List<ObjectAssociation> list =
objectSpecification.getAssociations(
Contributed.INCLUDED,
Filters.and(
associationFilter,
associationsWith(visibility)
));
return cast(list);
}
@SuppressWarnings("unchecked")
static <T> List<T> cast(final List list) {
return list;
}
static List<ObjectAction> actionsOf(
final ObjectSpecification objectSpec,
final SwaggerService.Visibility visibility,
final ClassExcluder classExcluder) {
final List<ActionType> actionTypes = actionTypesFor(visibility);
return objectSpec.getObjectActions(actionTypes, Contributed.INCLUDED, new Filter<ObjectAction>() {
@Override
public boolean accept(final ObjectAction objectAction) {
return !classExcluder.exclude(objectAction) &&
!visibility.isPublic() || isVisibleForPublic(objectAction);
}
});
}
static String roSpec(final String section) {
return "RO Spec v1.0, section " + section;
}
static Response withCachingHeaders(final Response response, final Caching caching) {
caching.withHeaders(response);
return response;
}
static List<ActionType> actionTypesFor(final SwaggerService.Visibility visibility) {
switch (visibility) {
case PUBLIC:
return Arrays.asList(ActionType.USER);
case PRIVATE:
return Arrays.asList(ActionType.USER);
case PRIVATE_WITH_PROTOTYPING:
return Arrays.asList(ActionType.USER, ActionType.PROTOTYPE);
}
throw new IllegalArgumentException("Unrecognized type '" + visibility + "'");
}
}