Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com)
*
* WSO2 LLC. 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 io.ballerina.modelgenerator.commons;

/**
* Represents read-only metadata for a service.
*
* @param metadataKey The key/name of the metadata field
* @param displayName The display name for the metadata field
* @param kind The kind/category of the metadata field (e.g., ANNOTATION, SERVICE_DESCRIPTION, LISTENER_PARAM)
*
* @since 1.3.0
*/
public record ReadOnlyMetaData(
String metadataKey,
String displayName,
String kind
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,35 @@ public List<Annotation> getAnnotationAttachments(String org, String packageName,

}

public List<ReadOnlyMetaData> getReadOnlyMetaData(String orgName, String packageName, String serviceType) {
String sql = "SELECT " +
"metadata_key, " +
"display_name, " +
"kind " +
"FROM ServiceReadOnlyMetaData srmd " +
"JOIN Package p ON srmd.package_id = p.package_id " +
"WHERE p.name = ? AND p.org = ? ";
try (Connection conn = DriverManager.getConnection(dbPath);
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, packageName);
stmt.setString(2, orgName);

ResultSet rs = stmt.executeQuery();
List<ReadOnlyMetaData> metaDataList = new ArrayList<>();
while (rs.next()) {
metaDataList.add(new ReadOnlyMetaData(
rs.getString("metadata_key"),
rs.getString("display_name"),
rs.getString("kind")
));
}
return metaDataList;
} catch (SQLException e) {
Logger.getGlobal().severe("Error executing query: " + e.getMessage());
return List.of();
}
}

// Helper builder class
private static class ParameterDataBuilder {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.ballerina.projects.Document;
import io.ballerina.projects.Project;
import io.ballerina.servicemodelgenerator.extension.builder.service.AiChatServiceBuilder;
import io.ballerina.servicemodelgenerator.extension.builder.service.AsbServiceBuilder;
import io.ballerina.servicemodelgenerator.extension.builder.service.DefaultServiceBuilder;
import io.ballerina.servicemodelgenerator.extension.builder.service.GraphqlServiceBuilder;
import io.ballerina.servicemodelgenerator.extension.builder.service.HttpServiceBuilder;
Expand Down Expand Up @@ -54,6 +55,7 @@
import java.util.function.Supplier;

import static io.ballerina.servicemodelgenerator.extension.util.Constants.AI;
import static io.ballerina.servicemodelgenerator.extension.util.Constants.ASB;
import static io.ballerina.servicemodelgenerator.extension.util.Constants.GRAPHQL;
import static io.ballerina.servicemodelgenerator.extension.util.Constants.HTTP;
import static io.ballerina.servicemodelgenerator.extension.util.Constants.KAFKA;
Expand All @@ -77,6 +79,7 @@ public class ServiceBuilderRouter {
put(GRAPHQL, GraphqlServiceBuilder::new);
put(MCP, McpServiceBuilder::new);
put(KAFKA, KafkaServiceBuilder::new);
put(ASB, AsbServiceBuilder::new);
}};

public static ServiceNodeBuilder getServiceBuilder(String protocol) {
Expand Down Expand Up @@ -108,7 +111,9 @@ public static Service getServiceFromSource(Node node, Project project,
workspaceManager, filePath, serviceMetadata.serviceType(), moduleID.orgName(),
moduleID.packageName(), moduleID.moduleName(), moduleID.version());
Service service = serviceBuilder.getModelFromSource(context);
service.getProperties().forEach((k, v) -> v.setAdvanced(false));
if (service != null) {
service.getProperties().forEach((k, v) -> v.setAdvanced(false));
}
return service;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,86 +96,6 @@ public abstract class AbstractFunctionBuilder implements NodeBuilder<Function> {

private static final String DEFAULT_FUNCTION_MODEL_LOCATION = "functions/%s_%s.json";

/**
* Get the model template for a given function.
*
* @param context the context information for retrieving the functional model template
* @return the model template
*/
@Override
public Optional<Function> getModelTemplate(GetModelContext context) {
String resourcePath = String.format(DEFAULT_FUNCTION_MODEL_LOCATION, context.serviceType(),
context.functionType());
InputStream resourceStream = Utils.class.getClassLoader()
.getResourceAsStream(resourcePath);
if (resourceStream == null) {
return Optional.empty();
}

try (JsonReader reader = new JsonReader(new InputStreamReader(resourceStream, StandardCharsets.UTF_8))) {
return Optional.of(new Gson().fromJson(reader, Function.class));
} catch (IOException e) {
return Optional.empty();
}
}

/**
* Get the list of text edits for the given function model for addition.
*
* @param context the context information for adding the service
* @return a map of file paths to lists of text edits
*/
@Override
public Map<String, List<TextEdit>> addModel(AddModelContext context) throws Exception {
return buildModel(context);
}

/**
* Get the list of text edits for the given function for updating.
*
* @param context the context information for updating the service
* @return a map of file paths to lists of text edits
*/
@Override
public Map<String, List<TextEdit>> updateModel(UpdateModelContext context) {
return buildUpdateModel(context);
}

/**
* Get the function model from the source code.
*
* @param context the context information for extracting the function model
* @return the ser extracted from the source code
*/
@Override
public Function getModelFromSource(ModelFromSourceContext context) {
FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) context.node();
Function functionModel;
if (functionDefinitionNode.parent() instanceof ClassDefinitionNode) {
functionModel = getObjectFunctionFromSource(CLASS, functionDefinitionNode, context.semanticModel());
} else {
functionModel = getFunctionInsideService(context);
}
functionModel.setEditable(true);
return functionModel;
}

private Function getFunctionInsideService(ModelFromSourceContext context) {
FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) context.node();
boolean isResource = functionDefinitionNode.qualifierList().stream()
.anyMatch(qualifier -> qualifier.text().equals(RESOURCE));
String functionName = isResource ? getPath(functionDefinitionNode.relativeResourcePath())
: functionDefinitionNode.functionName().text().trim();
Optional<ServiceTypeFunction> matchingServiceTypeFunction = ServiceDatabaseManager.getInstance()
.getMatchingServiceTypeFunction(context.orgName(), context.moduleName(), context.serviceType(),
functionName);
return matchingServiceTypeFunction.map(serviceTypeFunction ->
getServiceTypeBoundedFunctionFromSource(serviceTypeFunction,
functionDefinitionNode, context.semanticModel()))
.orElseGet(() -> getObjectFunctionFromSource(SERVICE_DIAGRAM,
functionDefinitionNode, context.semanticModel()));
}

static Function getServiceTypeBoundedFunctionFromSource(ServiceTypeFunction serviceTypeFunction,
FunctionDefinitionNode functionDefinitionNode,
SemanticModel semanticModel) {
Expand All @@ -198,14 +118,6 @@ static Function getServiceTypeBoundedFunctionFromSource(ServiceTypeFunction serv
return function;
}

/**
* @return kind of the function model
*/
@Override
public String kind() {
return "";
}

static Function getObjectFunctionFromSource(ServiceClassUtil.ServiceClassContext context,
FunctionDefinitionNode functionDefinitionNode,
SemanticModel semanticModel) {
Expand Down Expand Up @@ -339,7 +251,7 @@ public static Map<String, List<TextEdit>> buildUpdateModel(UpdateModelContext co
}
boolean isDefault = functionKind.equals(KIND_DEFAULT);

if (!isRemote && !isDefault) {
if (!isRemote && !isDefault) {
if (!functionName.equals(context.function().getAccessor().getValue())) {
edits.add(new TextEdit(Utils.toRange(nameRange), context.function().getAccessor().getValue()));
}
Expand Down Expand Up @@ -393,4 +305,92 @@ private static Parameter createParameter(String paramName, String paramKind, Str
parameterModel.getName().setValue(paramName);
return parameterModel;
}

/**
* Get the model template for a given function.
*
* @param context the context information for retrieving the functional model template
* @return the model template
*/
@Override
public Optional<Function> getModelTemplate(GetModelContext context) {
String resourcePath = String.format(DEFAULT_FUNCTION_MODEL_LOCATION, context.serviceType(),
context.functionType());
InputStream resourceStream = Utils.class.getClassLoader()
.getResourceAsStream(resourcePath);
if (resourceStream == null) {
return Optional.empty();
}

try (JsonReader reader = new JsonReader(new InputStreamReader(resourceStream, StandardCharsets.UTF_8))) {
return Optional.of(new Gson().fromJson(reader, Function.class));
} catch (IOException e) {
return Optional.empty();
}
}

/**
* Get the list of text edits for the given function model for addition.
*
* @param context the context information for adding the service
* @return a map of file paths to lists of text edits
*/
@Override
public Map<String, List<TextEdit>> addModel(AddModelContext context) throws Exception {
return buildModel(context);
}

/**
* Get the list of text edits for the given function for updating.
*
* @param context the context information for updating the service
* @return a map of file paths to lists of text edits
*/
@Override
public Map<String, List<TextEdit>> updateModel(UpdateModelContext context) {
return buildUpdateModel(context);
}

/**
* Get the function model from the source code.
*
* @param context the context information for extracting the function model
* @return the ser extracted from the source code
*/
@Override
public Function getModelFromSource(ModelFromSourceContext context) {
FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) context.node();
Function functionModel;
if (functionDefinitionNode.parent() instanceof ClassDefinitionNode) {
functionModel = getObjectFunctionFromSource(CLASS, functionDefinitionNode, context.semanticModel());
} else {
functionModel = getFunctionInsideService(context);
}
functionModel.setEditable(true);
return functionModel;
}

private Function getFunctionInsideService(ModelFromSourceContext context) {
FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) context.node();
boolean isResource = functionDefinitionNode.qualifierList().stream()
.anyMatch(qualifier -> qualifier.text().equals(RESOURCE));
String functionName = isResource ? getPath(functionDefinitionNode.relativeResourcePath())
: functionDefinitionNode.functionName().text().trim();
Optional<ServiceTypeFunction> matchingServiceTypeFunction = ServiceDatabaseManager.getInstance()
.getMatchingServiceTypeFunction(context.orgName(), context.moduleName(), context.serviceType(),
functionName);
return matchingServiceTypeFunction.map(serviceTypeFunction ->
getServiceTypeBoundedFunctionFromSource(serviceTypeFunction,
functionDefinitionNode, context.semanticModel()))
.orElseGet(() -> getObjectFunctionFromSource(SERVICE_DIAGRAM,
functionDefinitionNode, context.semanticModel()));
}

/**
* @return kind of the function model
*/
@Override
public String kind() {
return "";
}
}
Loading
Loading