001/**
002 * Copyright (C) 2006-2025 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.server.api;
017
018import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
019import static javax.ws.rs.core.MediaType.APPLICATION_OCTET_STREAM;
020import static org.eclipse.microprofile.openapi.annotations.enums.ParameterIn.PATH;
021import static org.eclipse.microprofile.openapi.annotations.enums.ParameterIn.QUERY;
022import static org.eclipse.microprofile.openapi.annotations.enums.SchemaType.OBJECT;
023import static org.eclipse.microprofile.openapi.annotations.enums.SchemaType.STRING;
024
025import java.util.Map;
026
027import javax.ws.rs.Consumes;
028import javax.ws.rs.DefaultValue;
029import javax.ws.rs.GET;
030import javax.ws.rs.POST;
031import javax.ws.rs.Path;
032import javax.ws.rs.PathParam;
033import javax.ws.rs.Produces;
034import javax.ws.rs.QueryParam;
035import javax.ws.rs.core.MediaType;
036import javax.ws.rs.core.Response;
037import javax.ws.rs.core.StreamingOutput;
038
039import org.eclipse.microprofile.openapi.annotations.Operation;
040import org.eclipse.microprofile.openapi.annotations.media.Content;
041import org.eclipse.microprofile.openapi.annotations.media.Schema;
042import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
043import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
044import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
045import org.eclipse.microprofile.openapi.annotations.tags.Tag;
046import org.talend.sdk.component.server.front.model.ComponentDetailList;
047import org.talend.sdk.component.server.front.model.ComponentIndices;
048import org.talend.sdk.component.server.front.model.Dependencies;
049import org.talend.sdk.component.server.front.model.error.ErrorPayload;
050
051@Path("component")
052@Consumes(MediaType.APPLICATION_JSON)
053@Produces(MediaType.APPLICATION_JSON)
054@Tag(name = "Component", description = "Endpoints related to component metadata access.")
055public interface ComponentResource {
056
057    String IMAGE_SVG_XML = "image/svg+xml";
058
059    @GET
060    @Path("dependencies")
061    @Operation(description = "Returns a list of dependencies for the given components. "
062            + "IMPORTANT: don't forget to add the component itself since it will not be part of the dependencies."
063            + "Then you can use /dependency/{id} to download the binary.")
064    @APIResponse(responseCode = "200",
065            description = "The list of dependencies per component.",
066            content = @Content(mediaType = APPLICATION_JSON))
067    Dependencies getDependencies(@QueryParam("identifier") @Parameter(name = "identifier",
068            description = "The identifier id to request. Repeat this parameter to request more than one element.",
069            in = QUERY) String[] ids);
070
071    @GET
072    @Path("dependency/{id}")
073    @Produces(MediaType.APPLICATION_OCTET_STREAM)
074    @Operation(description = "Return a binary of the dependency represented by `id`. "
075            + "It can be maven coordinates for dependencies or a component id.")
076    @APIResponse(responseCode = "200",
077            description = "The dependency binary (jar).",
078            content = @Content(mediaType = APPLICATION_OCTET_STREAM))
079    @APIResponse(responseCode = "404",
080            description = "If the plugin is missing, payload will be an ErrorPayload with the code PLUGIN_MISSING.",
081            content = @Content(mediaType = APPLICATION_JSON,
082                    schema = @Schema(type = OBJECT, implementation = ErrorPayload.class)))
083    StreamingOutput getDependency(@PathParam("id") @Parameter(name = "id",
084            description = "Dependency identifier for component/configurationType or maven coordinate.  \n" +
085                    "Example: `/api/v1/component/dependency/org.apache.commons:commons-lang3:jar:3.12.0`.",
086            in = PATH) String id);
087
088    @GET
089    @Path("index")
090    @Operation(operationId = "getComponentIndex",
091            description = "Returns the list of available components.")
092    @APIResponse(responseCode = "200",
093            description = "The index of available components.",
094            content = @Content(mediaType = APPLICATION_OCTET_STREAM))
095    ComponentIndices getIndex(
096            @QueryParam("language") @DefaultValue("en") @Parameter(name = "language",
097                    description = "Response language in i18n format.", in = QUERY,
098                    schema = @Schema(type = STRING, defaultValue = "en")) String language,
099            @QueryParam("includeIconContent") @DefaultValue("false") @Parameter(name = "includeIconContent",
100                    description = "Should the icon binary format be included in the payload.  " +
101                            "Default is `false`.",
102                    in = QUERY,
103                    schema = @Schema(type = STRING, defaultValue = "en")) boolean includeIconContent,
104            @QueryParam("q") @Parameter(name = "q",
105                    description = "Query in simple query language to filter components. "
106                            + "It provides access to the component `plugin`, `name`, `id` and `metadata` of the first configuration property. "
107                            + "Ex: `(id = AYETAE658349453) AND (metadata[configurationtype::type] = dataset) AND (plugin = jdbc-component) AND "
108                            + "(name = input)`.",
109                    in = QUERY, schema = @Schema(type = STRING)) String query,
110            @QueryParam("theme") @Parameter(name = "theme",
111                    description = "Theme selector (light/dark). Defaults to light.") String theme);
112
113    @GET
114    @Path("icon/family/{id}")
115    @Produces({ APPLICATION_JSON, APPLICATION_OCTET_STREAM })
116    @Operation(description = "Returns the icon for a family.")
117    @APIResponse(responseCode = "200",
118            description = "Returns a particular family icon in raw bytes.",
119            content = @Content(mediaType = APPLICATION_OCTET_STREAM))
120    @APIResponse(responseCode = "404",
121            description = "The family or icon is not found.",
122            content = @Content(mediaType = APPLICATION_JSON,
123                    schema = @Schema(type = OBJECT, implementation = ErrorPayload.class)))
124    Response familyIcon(
125            @PathParam("id") @Parameter(name = "id", description = "Family identifier.", in = PATH) String id,
126            @QueryParam("theme") @Parameter(name = "theme",
127                    description = "Theme selector (light/dark). Defaults to light.") String theme);
128
129    @GET
130    @Path("icon/{id}")
131    @Produces({ APPLICATION_JSON, APPLICATION_OCTET_STREAM })
132    @Operation(description = "Returns a particular component icon in raw bytes.")
133    @APIResponse(responseCode = "200",
134            description = "The component icon in binary form.",
135            content = @Content(mediaType = APPLICATION_OCTET_STREAM))
136    @APIResponse(responseCode = "404",
137            description = "The family or icon is not found.",
138            content = @Content(mediaType = APPLICATION_JSON))
139    Response icon(
140            @PathParam("id") @Parameter(name = "id", description = "Component icon identifier.", in = PATH) String id,
141            @QueryParam("theme") @Parameter(name = "theme",
142                    description = "Theme selector (light/dark). Defaults to light.") String theme);
143
144    @GET
145    @Path("icon/custom/{familyId}/{iconKey}")
146    @Produces({ APPLICATION_JSON, APPLICATION_OCTET_STREAM })
147    @Operation(description = "Returns a particular key icon in raw bytes.")
148    @APIResponse(responseCode = "200",
149            description = "The icon in binary form.",
150            content = @Content(mediaType = APPLICATION_OCTET_STREAM))
151    @APIResponse(responseCode = "404",
152            description = "The family or icon is not found.",
153            content = @Content(mediaType = APPLICATION_JSON))
154    Response icon(
155            @PathParam("familyId") @Parameter(name = "familyId", description = "family identifier.",
156                    in = PATH) String familyId,
157            @PathParam("iconKey") @Parameter(name = "iconKey", description = "icon key.", in = PATH) String iconKey,
158            @QueryParam("theme") @Parameter(name = "theme",
159                    description = "Theme selector (light/dark). Defaults to light.") String theme);
160
161    @GET
162    @Path("icon/index")
163    @Produces({ APPLICATION_JSON, IMAGE_SVG_XML })
164    @Operation(description = "Returns list of available svg icons.")
165    @APIResponse(responseCode = "200", description = "The icon list.",
166            content = @Content(mediaType = IMAGE_SVG_XML))
167    @APIResponse(responseCode = "404", description = "No icon found.", content = @Content(mediaType = APPLICATION_JSON))
168    Response getIconIndex(
169            @QueryParam("theme") @Parameter(name = "theme",
170                    description = "Theme selector (light/dark/all). Defaults to light.") String theme);
171
172    @POST
173    @Path("migrate/{id}/{configurationVersion}")
174    @Operation(operationId = "migrateComponent",
175            description = "Allows to migrate a component configuration without calling any component execution.")
176    @APIResponse(responseCode = "200",
177            description = "New configuration for that component (or the same if no migration was needed).",
178            content = @Content(mediaType = APPLICATION_JSON))
179    @APIResponse(responseCode = "404",
180            description = "The component is not found.",
181            content = @Content(mediaType = APPLICATION_JSON,
182                    schema = @Schema(type = OBJECT, implementation = ErrorPayload.class)))
183    Map<String, String> migrate(
184            @PathParam("id") @Parameter(name = "id",
185                    description = "Component identifier.", in = PATH) String id,
186            @PathParam("configurationVersion") @Parameter(name = "configurationVersion",
187                    description = "Configuration version sent, corresponding to the body content.",
188                    in = PATH) int version,
189            @RequestBody(description = "Actual configuration in key/value json form.", required = true,
190                    content = @Content(mediaType = APPLICATION_JSON,
191                            schema = @Schema(type = OBJECT))) Map<String, String> config);
192
193    @GET
194    @Path("details")
195    @Operation(operationId = "getComponentDetail",
196            description = "Returns the set of metadata about one or multiples components identified by their 'id'.")
197    @APIResponse(responseCode = "200",
198            description = "List of details for the requested components.",
199            content = @Content(mediaType = APPLICATION_JSON))
200    @APIResponse(responseCode = "400",
201            description = "Some identifiers were not valid.",
202            content = @Content(mediaType = APPLICATION_JSON,
203                    schema = @Schema(type = OBJECT, implementation = SampleErrorForBulk.class)))
204    ComponentDetailList getDetail(
205            @QueryParam("language") @DefaultValue("en") @Parameter(name = "language",
206                    description = "Response language in i18n format.",
207                    in = QUERY,
208                    schema = @Schema(type = STRING, defaultValue = "en")) String language,
209            @QueryParam("identifiers") @Parameter(name = "identifiers",
210                    description = "The identifier id to request. " +
211                            "Repeat this parameter to request more than one element.",
212
213                    in = QUERY) String[] ids);
214
215    // @Unused, only for sample
216    class SampleErrorForBulk {
217
218        private ErrorPayload error1;
219
220        private ErrorPayload error2;
221    }
222}