44import com .fasterxml .jackson .databind .ObjectMapper ;
55import org .springframework .beans .factory .annotation .Value ;
66import org .springframework .stereotype .Service ;
7- import org .springframework .web .client .RestTemplate ;
8- import org .springframework .http .*;
9-
10- import java .util .Collections ;
11- import java .util .List ;
12- import java .util .Map ;
7+ import java .net .URI ;
8+ import java .net .http .HttpClient ;
9+ import java .net .http .HttpRequest ;
10+ import java .net .http .HttpResponse ;
11+ import java .util .*;
1312
1413@ Service
1514public class AIService {
@@ -20,72 +19,79 @@ public class AIService {
2019 @ Value ("${ai.api.key}" )
2120 private String apiKey ;
2221
22+ private final HttpClient httpClient = HttpClient .newHttpClient ();
23+ private final ObjectMapper objectMapper = new ObjectMapper ();
24+
2325 public String generateCodeFromPrompt (String className , String prompt ) {
2426 String refinedPrompt = refinePrompt (className , prompt );
2527 String sanitizedPrompt = sanitizeInput (refinedPrompt );
2628
27- RestTemplate restTemplate = new RestTemplate ();
28- HttpHeaders headers = new HttpHeaders ();
29- headers .set ("Authorization" , "Bearer " + apiKey );
30- headers .setContentType (MediaType .APPLICATION_JSON );
31-
32- ObjectMapper objectMapper = new ObjectMapper ();
33- Map <String , String > payload = Collections .singletonMap ("inputs" , sanitizedPrompt );
29+ Map <String , String > payload = Map .of ("inputs" , sanitizedPrompt );
3430 String requestBody ;
3531 try {
3632 requestBody = objectMapper .writeValueAsString (payload );
3733 } catch (JsonProcessingException e ) {
3834 throw new RuntimeException ("Error processing JSON request" , e );
3935 }
4036
41- HttpEntity <String > request = new HttpEntity <>(requestBody , headers );
42- ResponseEntity <String > response = restTemplate .exchange (apiUrl , HttpMethod .POST , request , String .class );
37+ HttpRequest request = HttpRequest .newBuilder ()
38+ .uri (URI .create (apiUrl ))
39+ .header ("Authorization" , "Bearer " + apiKey )
40+ .header ("Content-Type" , "application/json" )
41+ .POST (HttpRequest .BodyPublishers .ofString (requestBody ))
42+ .build ();
4343
44- if (response .getStatusCode () == HttpStatus .OK ) {
45- return extractGeneratedText (response .getBody ());
44+ try {
45+ HttpResponse <String > response = httpClient .send (request , HttpResponse .BodyHandlers .ofString ());
46+ return response .statusCode () == 200 ? extractGeneratedText (response .body ()) : "Error generating code." ;
47+ } catch (Exception e ) {
48+ return "Error connecting to AI API: " + e .getMessage ();
4649 }
47- return "Error generating code." ;
4850 }
4951
5052 private String extractGeneratedText (String jsonResponse ) {
5153 try {
52- ObjectMapper objectMapper = new ObjectMapper ();
53- List < Map < String , Object >> responseList = objectMapper . readValue ( jsonResponse , List .class );
54+ List < ResponseData > responseList = objectMapper . readValue ( jsonResponse , objectMapper . getTypeFactory ()
55+ . constructCollectionType ( List . class , ResponseData .class ) );
5456
55- if (!responseList .isEmpty () && responseList .get (0 ).containsKey ("generated_text" )) {
56- return responseList .get (0 ).get ("generated_text" ).toString ().trim ();
57- }
57+ return responseList .stream ()
58+ .findFirst ()
59+ .map (ResponseData ::generated_text )
60+ .map (this ::extractJavaCode )
61+ .orElse ("Error processing response." );
5862 } catch (Exception e ) {
59- e . printStackTrace () ;
63+ return "Error processing response." ;
6064 }
61- return "Error processing response." ;
65+ }
66+
67+ private String extractJavaCode (String response ) {
68+ int startIndex = response .indexOf ("```java" );
69+ if (startIndex != -1 ) {
70+ response = response .substring (startIndex + 7 );
71+ }
72+
73+ int endIndex = response .lastIndexOf ("```" );
74+ if (endIndex != -1 ) {
75+ response = response .substring (0 , endIndex );
76+ }
77+
78+ return response .strip ();
6279 }
6380
6481 private String refinePrompt (String className , String prompt ) {
65- return "Generate a single complete Java class named '" + className + "' based on the following description:\n "
66- + prompt + "\n \n "
67- + "The class should follow Java best practices and include all necessary imports.\n "
68- + "The output must be a complete Java class, formatted as:\n "
69- + "```java\n "
70- + "public class " + className + " {\n "
71- + " // Class implementation\n "
72- + "}\n "
73- + "```\n "
74- + "Do not include summaries or explanations, only return the raw class definition." ;
82+ return STR ."""
83+ Generate only a single complete Java class named '\{className }' based on the following description:
84+ \{prompt }
85+
86+ Return only the Java code without any explanations, descriptions, comments, or summaries.
87+ """ ;
7588 }
7689
77- public String sanitizeInput (String input ) {
78- if (input == null || input .isBlank ()) {
79- return "" ;
80- }
81- StringBuilder sanitized = new StringBuilder ();
82- for (char c : input .toCharArray ()) {
83- if (c >= 0x00 && c <= 0x1F ) {
84- sanitized .append (String .format ("\\ u%04x" , (int ) c ));
85- } else {
86- sanitized .append (c );
87- }
88- }
89- return sanitized .toString ();
90+ private String sanitizeInput (String input ) {
91+ return Optional .ofNullable (input )
92+ .map (str -> str .replaceAll ("[\\ p{Cntrl}&&[^\r \n \t ]]" , "" ))
93+ .orElse ("" );
9094 }
95+
96+ private record ResponseData (String generated_text ) {}
9197}
0 commit comments