001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.isis.viewer.restfulobjects.rendering.service.swagger; 020 021import java.util.Optional; 022 023import javax.inject.Inject; 024import javax.inject.Named; 025 026import org.apache.isis.applib.IsisModuleApplib; 027import org.apache.isis.applib.annotation.Action; 028import org.apache.isis.applib.annotation.ActionLayout; 029import org.apache.isis.applib.annotation.DomainService; 030import org.apache.isis.applib.annotation.DomainServiceLayout; 031import org.apache.isis.applib.annotation.MemberOrder; 032import org.apache.isis.applib.annotation.ParameterLayout; 033import org.apache.isis.applib.annotation.RestrictTo; 034import org.apache.isis.applib.annotation.SemanticsOf; 035import org.apache.isis.applib.services.registry.ServiceRegistry; 036import org.apache.isis.applib.services.swagger.SwaggerService; 037import org.apache.isis.applib.value.Clob; 038import org.apache.isis.applib.value.LocalResourcePath; 039import org.apache.isis.core.commons.internal.base._Strings; 040import org.apache.isis.core.config.RestEasyConfiguration; 041 042 043@Named("isisApplib.SwaggerServiceMenu") 044@DomainService(objectType = "isisApplib.SwaggerServiceMenu") 045@DomainServiceLayout( 046 named = "Prototyping", 047 menuBar = DomainServiceLayout.MenuBar.SECONDARY 048) 049public class SwaggerServiceMenu { 050 051 private final SwaggerService swaggerService; 052 private final ServiceRegistry serviceRegistry; 053 private final RestEasyConfiguration restEasyConfiguration; 054 private final String basePath; 055 056 @Inject 057 public SwaggerServiceMenu( 058 final SwaggerService swaggerService, 059 final ServiceRegistry serviceRegistry, 060 final RestEasyConfiguration restEasyConfiguration) { 061 this.swaggerService = swaggerService; 062 this.serviceRegistry = serviceRegistry; 063 this.restEasyConfiguration = restEasyConfiguration; 064 this.basePath = this.restEasyConfiguration.getJaxrs().getDefaultPath() + "/"; 065 } 066 067 public static abstract class ActionDomainEvent extends IsisModuleApplib.ActionDomainEvent<SwaggerServiceMenu> { } 068 public static class OpenSwaggerUiDomainEvent extends ActionDomainEvent { } 069 070 @Action( 071 semantics = SemanticsOf.SAFE, 072 domainEvent = OpenSwaggerUiDomainEvent.class, 073 restrictTo = RestrictTo.PROTOTYPING 074 ) 075 @ActionLayout( 076 cssClassFa = "fa-external-link" 077 ) 078 @MemberOrder(sequence="500.600.1") 079 public LocalResourcePath openSwaggerUi() { 080 return new LocalResourcePath("/swagger-ui/index.thtml"); 081 } 082 083 public String disableOpenSwaggerUi() { 084 return disableReasonWhenRequiresROViewer(); 085 } 086 087 public static class OpenRestApiDomainEvent extends ActionDomainEvent { } 088 089 @Action( 090 semantics = SemanticsOf.SAFE, 091 domainEvent = OpenSwaggerUiDomainEvent.class, 092 restrictTo = RestrictTo.PROTOTYPING 093 ) 094 @ActionLayout( 095 cssClassFa = "fa-external-link" 096 ) 097 @MemberOrder(sequence="500.600.2") 098 public LocalResourcePath openRestApi() { 099 return new LocalResourcePath(basePath); 100 } 101 102 public String disableOpenRestApi() { 103 return disableReasonWhenRequiresROViewer(); 104 } 105 106 public static class DownloadSwaggerSpecDomainEvent extends ActionDomainEvent { } 107 108 @Action( 109 semantics = SemanticsOf.SAFE, 110 domainEvent = DownloadSwaggerSpecDomainEvent.class, 111 restrictTo = RestrictTo.PROTOTYPING 112 ) 113 @ActionLayout( 114 cssClassFa = "fa-download" 115 ) 116 @MemberOrder(sequence="500.600.3") 117 public Clob downloadSwaggerSchemaDefinition( 118 @ParameterLayout(named = "Filename") 119 final String fileNamePrefix, 120 final SwaggerService.Visibility visibility, 121 final SwaggerService.Format format) { 122 123 final String fileName = buildFileName(fileNamePrefix, visibility, format); 124 final String spec = swaggerService.generateSwaggerSpec(visibility, format); 125 return new Clob(fileName, format.mediaType(), spec); 126 } 127 128 public String default0DownloadSwaggerSchemaDefinition() { 129 return "swagger"; 130 } 131 public SwaggerService.Visibility default1DownloadSwaggerSchemaDefinition() { 132 return SwaggerService.Visibility.PRIVATE; 133 } 134 public SwaggerService.Format default2DownloadSwaggerSchemaDefinition() { 135 return SwaggerService.Format.YAML; 136 } 137 138 // -- HELPER 139 140 private String disableReasonWhenRequiresROViewer() { 141 final Optional<?> moduleIfAny = serviceRegistry.lookupBeanById("isisRoViewer.WebModuleJaxrsRestEasy4"); 142 return moduleIfAny.isPresent() 143 ? null 144 : "RestfulObjects viewer is not configured"; 145 } 146 147 private static String buildFileName( 148 String fileNamePrefix, 149 final SwaggerService.Visibility visibility, 150 final SwaggerService.Format format) { 151 final String formatLower = format.name().toLowerCase(); 152 int i = fileNamePrefix.lastIndexOf("." + formatLower); 153 if(i > 0) { 154 fileNamePrefix = fileNamePrefix.substring(0, i); 155 } 156 return _Strings.asFileNameWithExtension( 157 fileNamePrefix + "-" + visibility.name().toLowerCase(), 158 formatLower); 159 } 160 161 162}