Skip to content

Commit ed970e1

Browse files
authored
Merge pull request #672 from VellummyilumVinoth/refactor-libraries-migration
Refactor migration libraries API
2 parents 7beba82 + 23e49de commit ed970e1

34 files changed

+3397
-1508
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com)
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package io.ballerina.flowmodelgenerator.core;
20+
21+
import io.ballerina.compiler.api.SemanticModel;
22+
import io.ballerina.compiler.api.symbols.ClassSymbol;
23+
import io.ballerina.compiler.api.symbols.Qualifier;
24+
import io.ballerina.flowmodelgenerator.core.model.Client;
25+
import io.ballerina.flowmodelgenerator.core.model.LibraryFunction;
26+
import io.ballerina.flowmodelgenerator.core.model.TypeDef;
27+
import io.ballerina.modelgenerator.commons.FunctionData;
28+
import io.ballerina.modelgenerator.commons.FunctionDataBuilder;
29+
import io.ballerina.modelgenerator.commons.ModuleInfo;
30+
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
import java.util.Optional;
34+
35+
/**
36+
* Handler for processing CLASS symbols from semantic model.
37+
* Extracts client classes and normal classes with their methods.
38+
*
39+
* @since 1.0.1
40+
*/
41+
public class ClassSymbolHandler {
42+
43+
private ClassSymbolHandler() {
44+
// Prevent instantiation
45+
}
46+
47+
/**
48+
* Processes a CLASS symbol and returns either a Client or TypeDef.
49+
*
50+
* @param classSymbol the class symbol to process
51+
* @param semanticModel the semantic model
52+
* @param moduleInfo the module information
53+
* @param org the organization name
54+
* @param packageName the package name
55+
* @return Optional containing either Client or TypeDef, or empty if not public
56+
*/
57+
public static Optional<Object> process(ClassSymbol classSymbol,
58+
SemanticModel semanticModel,
59+
ModuleInfo moduleInfo,
60+
String org,
61+
String packageName) {
62+
// Process only PUBLIC classes: CLIENT classes (connectors) and normal classes
63+
if (!classSymbol.qualifiers().contains(Qualifier.PUBLIC)) {
64+
return Optional.empty();
65+
}
66+
67+
boolean isClient = classSymbol.qualifiers().contains(Qualifier.CLIENT);
68+
String className = classSymbol.getName().orElse(isClient ? "Client" : "Class");
69+
70+
FunctionData.Kind classKind = isClient ? FunctionData.Kind.CONNECTOR : FunctionData.Kind.CLASS_INIT;
71+
72+
FunctionData classData = new FunctionDataBuilder()
73+
.semanticModel(semanticModel)
74+
.moduleInfo(moduleInfo)
75+
.name(className)
76+
.parentSymbol(classSymbol)
77+
.functionResultKind(classKind)
78+
.build();
79+
80+
List<LibraryFunction> functions = new ArrayList<>();
81+
82+
// Add the constructor/init function first
83+
LibraryFunction constructor = LibraryModelConverter.functionDataToModel(classData, org, packageName);
84+
constructor.setName("init"); // Override name to "init" for constructor
85+
functions.add(constructor);
86+
87+
// Then add all other methods (remote functions, resource functions, etc.)
88+
List<FunctionData> classMethods = new FunctionDataBuilder()
89+
.semanticModel(semanticModel)
90+
.moduleInfo(moduleInfo)
91+
.parentSymbolType(className)
92+
.parentSymbol(classSymbol)
93+
.buildChildNodes();
94+
95+
for (FunctionData method : classMethods) {
96+
LibraryFunction methodFunc = LibraryModelConverter.functionDataToModel(method, org, packageName);
97+
functions.add(methodFunc);
98+
}
99+
100+
if (isClient) {
101+
Client client = new Client(className, classData.description());
102+
client.setFunctions(functions);
103+
return Optional.of(client);
104+
} else {
105+
TypeDef typeDef = new TypeDef();
106+
typeDef.setName(className);
107+
typeDef.setDescription(classData.description());
108+
typeDef.setFunctions(functions);
109+
return Optional.of(typeDef);
110+
}
111+
}
112+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com)
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package io.ballerina.flowmodelgenerator.core;
20+
21+
import io.ballerina.compiler.api.symbols.ConstantSymbol;
22+
import io.ballerina.compiler.api.symbols.Qualifier;
23+
import io.ballerina.compiler.api.symbols.TypeSymbol;
24+
import io.ballerina.compiler.api.values.ConstantValue;
25+
import io.ballerina.flowmodelgenerator.core.model.Type;
26+
import io.ballerina.flowmodelgenerator.core.model.TypeDef;
27+
import io.ballerina.modelgenerator.commons.TypeDefData;
28+
29+
import java.util.Optional;
30+
31+
/**
32+
* Handler for processing CONSTANT symbols from semantic model.
33+
*
34+
* @since 1.0.1
35+
*/
36+
public class ConstantSymbolHandler {
37+
38+
private ConstantSymbolHandler() {
39+
}
40+
41+
public static Optional<TypeDef> process(ConstantSymbol constantSymbol,
42+
String org,
43+
String packageName) {
44+
if (!constantSymbol.qualifiers().contains(Qualifier.PUBLIC)) {
45+
return Optional.empty();
46+
}
47+
48+
TypeDefData constantData = TypeDefDataBuilder.buildFromConstant(constantSymbol);
49+
TypeDef typeDef = LibraryModelConverter.typeDefDataToModel(constantData, org, packageName);
50+
51+
// Add varType using ConstantValue
52+
String varTypeName = "";
53+
Object constValue = constantSymbol.constValue();
54+
if (constValue instanceof ConstantValue constantValue) {
55+
varTypeName = constantValue.valueType().typeKind().getName();
56+
}
57+
58+
// Fallback to type descriptor if constValue is null or not ConstantValue
59+
if (varTypeName.isEmpty()) {
60+
TypeSymbol typeSymbol = constantSymbol.typeDescriptor();
61+
if (typeSymbol != null && !typeSymbol.signature().isEmpty()) {
62+
varTypeName = typeSymbol.signature();
63+
}
64+
}
65+
66+
Type varType = new Type(varTypeName);
67+
typeDef.setVarType(varType);
68+
69+
return Optional.of(typeDef);
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com)
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package io.ballerina.flowmodelgenerator.core;
20+
21+
import com.google.gson.Gson;
22+
import com.google.gson.JsonArray;
23+
import com.google.gson.JsonElement;
24+
import io.ballerina.compiler.api.SemanticModel;
25+
import io.ballerina.flowmodelgenerator.core.model.Library;
26+
import io.ballerina.flowmodelgenerator.core.model.Service;
27+
import io.ballerina.modelgenerator.commons.ModuleInfo;
28+
import io.ballerina.modelgenerator.commons.PackageUtil;
29+
30+
import java.io.IOException;
31+
import java.sql.SQLException;
32+
import java.util.ArrayList;
33+
import java.util.List;
34+
import java.util.Map;
35+
import java.util.Optional;
36+
37+
/**
38+
* Core orchestrator for Copilot library operations.
39+
* Coordinates between database access, symbol processing, and service loading.
40+
*
41+
* @since 1.0.1
42+
*/
43+
public class CopilotLibraryManager {
44+
45+
private static final Gson GSON = new Gson();
46+
47+
/**
48+
* Loads all libraries from the database.
49+
* Returns a list of libraries with name and description only.
50+
*
51+
* @return List of Library objects containing name and description
52+
*/
53+
public List<Library> loadLibrariesFromDatabase() {
54+
List<Library> libraries = new ArrayList<>();
55+
56+
try {
57+
Map<String, String> packageToDescriptionMap = LibraryDatabaseAccessor.loadAllPackages();
58+
59+
for (Map.Entry<String, String> entry : packageToDescriptionMap.entrySet()) {
60+
Library library = new Library(entry.getKey(), entry.getValue());
61+
libraries.add(library);
62+
}
63+
} catch (IOException | SQLException e) {
64+
throw new RuntimeException("Failed to load libraries from database: " + e.getMessage(), e);
65+
}
66+
67+
return libraries;
68+
}
69+
70+
/**
71+
* Loads filtered libraries using the semantic model.
72+
* Returns libraries with full details including clients, functions, typedefs, and services.
73+
*
74+
* @param libraryNames Array of library names in "org/package_name" format to filter
75+
* @return List of Library objects with complete information
76+
*/
77+
public List<Library> loadFilteredLibraries(String[] libraryNames) {
78+
List<Library> libraries = new ArrayList<>();
79+
80+
for (String libraryName : libraryNames) {
81+
// Parse library name "org/package_name"
82+
String[] parts = libraryName.split("/");
83+
if (parts.length != 2) {
84+
continue; // Skip invalid format
85+
}
86+
String org = parts[0];
87+
String packageName = parts[1];
88+
89+
// Create module info (use latest version by passing null)
90+
ModuleInfo moduleInfo = new ModuleInfo(org, packageName, org + "/" +
91+
packageName, null);
92+
93+
// Get semantic model for the module
94+
Optional<SemanticModel> optSemanticModel = PackageUtil.getSemanticModel(org, packageName);
95+
if (optSemanticModel.isEmpty()) {
96+
continue; // Skip if semantic model not found
97+
}
98+
99+
SemanticModel semanticModel = optSemanticModel.get();
100+
101+
// Get the package description from database
102+
String description = LibraryDatabaseAccessor.getPackageDescription(org, packageName).orElse("");
103+
104+
// Create library object
105+
Library library = new Library(libraryName, description);
106+
107+
// Process module symbols to extract clients, functions, and typedefs
108+
SymbolProcessor.SymbolProcessingResult symbolResult = SymbolProcessor.processModuleSymbols(
109+
semanticModel,
110+
moduleInfo,
111+
org,
112+
packageName
113+
);
114+
115+
library.setClients(symbolResult.getClients());
116+
library.setFunctions(symbolResult.getFunctions());
117+
library.setTypeDefs(symbolResult.getTypeDefs());
118+
119+
// Load services from both inbuilt triggers and generic services
120+
// For now, keep using JSON and convert to Service POJOs
121+
JsonArray servicesJson = ServiceLoader.loadAllServices(libraryName);
122+
List<Service> services = new ArrayList<>();
123+
for (JsonElement serviceElement : servicesJson) {
124+
Service service = GSON.fromJson(serviceElement, Service.class);
125+
services.add(service);
126+
}
127+
library.setServices(services);
128+
129+
libraries.add(library);
130+
}
131+
132+
return libraries;
133+
}
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2026, WSO2 LLC. (http://www.wso2.com)
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
package io.ballerina.flowmodelgenerator.core;
20+
21+
import io.ballerina.compiler.api.symbols.EnumSymbol;
22+
import io.ballerina.compiler.api.symbols.Qualifier;
23+
import io.ballerina.flowmodelgenerator.core.model.TypeDef;
24+
import io.ballerina.modelgenerator.commons.TypeDefData;
25+
26+
import java.util.Optional;
27+
28+
/**
29+
* Handler for processing ENUM symbols from semantic model.
30+
*
31+
* @since 1.0.1
32+
*/
33+
public class EnumSymbolHandler {
34+
35+
private EnumSymbolHandler() {
36+
}
37+
38+
public static Optional<TypeDef> process(EnumSymbol enumSymbol,
39+
String org,
40+
String packageName) {
41+
if (!enumSymbol.qualifiers().contains(Qualifier.PUBLIC)) {
42+
return Optional.empty();
43+
}
44+
45+
TypeDefData enumData = TypeDefDataBuilder.buildFromEnum(enumSymbol);
46+
TypeDef typeDef = LibraryModelConverter.typeDefDataToModel(enumData, org, packageName);
47+
return Optional.of(typeDef);
48+
}
49+
}

0 commit comments

Comments
 (0)