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}