View Javadoc
1   /*
2    * Copyright 2012-2025 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.entity;
17  
18  import java.io.Serializable;
19  import java.time.LocalDateTime;
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.Map;
23  
24  /**
25   * Represents a message in a chat conversation.
26   *
27   * @author FessProject
28   */
29  public class ChatMessage implements Serializable {
30  
31      private static final long serialVersionUID = 1L;
32  
33      /** The role identifier for user messages. */
34      public static final String ROLE_USER = "user";
35  
36      /** The role identifier for assistant messages. */
37      public static final String ROLE_ASSISTANT = "assistant";
38  
39      /** The unique identifier for this message. */
40      private String id;
41  
42      /** The role of the message sender (user or assistant). */
43      private String role;
44  
45      /** The content of the message. */
46      private String content;
47  
48      /** The timestamp when the message was created. */
49      private LocalDateTime timestamp;
50  
51      /** The list of sources referenced in this message. */
52      private List<ChatSource> sources;
53  
54      /** The HTML-rendered content for display. */
55      private String htmlContent;
56  
57      /**
58       * Default constructor.
59       */
60      public ChatMessage() {
61          this.timestamp = LocalDateTime.now();
62          this.sources = new ArrayList<>();
63      }
64  
65      /**
66       * Creates a new chat message with the specified role and content.
67       *
68       * @param role the message role
69       * @param content the message content
70       */
71      public ChatMessage(final String role, final String content) {
72          this();
73          this.role = role;
74          this.content = content;
75      }
76  
77      /**
78       * Creates a user message with the specified content.
79       *
80       * @param content the message content
81       * @return a new user message
82       */
83      public static ChatMessage userMessage(final String content) {
84          return new ChatMessage(ROLE_USER, content);
85      }
86  
87      /**
88       * Creates an assistant message with the specified content.
89       *
90       * @param content the message content
91       * @return a new assistant message
92       */
93      public static ChatMessage assistantMessage(final String content) {
94          return new ChatMessage(ROLE_ASSISTANT, content);
95      }
96  
97      /**
98       * Gets the message ID.
99       *
100      * @return the message ID
101      */
102     public String getId() {
103         return id;
104     }
105 
106     /**
107      * Sets the message ID.
108      *
109      * @param id the message ID
110      */
111     public void setId(final String id) {
112         this.id = id;
113     }
114 
115     /**
116      * Gets the message role.
117      *
118      * @return the message role
119      */
120     public String getRole() {
121         return role;
122     }
123 
124     /**
125      * Sets the message role.
126      *
127      * @param role the message role
128      */
129     public void setRole(final String role) {
130         this.role = role;
131     }
132 
133     /**
134      * Gets the message content.
135      *
136      * @return the message content
137      */
138     public String getContent() {
139         return content;
140     }
141 
142     /**
143      * Sets the message content.
144      *
145      * @param content the message content
146      */
147     public void setContent(final String content) {
148         this.content = content;
149     }
150 
151     /**
152      * Gets the message timestamp.
153      *
154      * @return the message timestamp
155      */
156     public LocalDateTime getTimestamp() {
157         return timestamp;
158     }
159 
160     /**
161      * Sets the message timestamp.
162      *
163      * @param timestamp the message timestamp
164      */
165     public void setTimestamp(final LocalDateTime timestamp) {
166         this.timestamp = timestamp;
167     }
168 
169     /**
170      * Gets the list of sources referenced in the message.
171      *
172      * @return the list of sources
173      */
174     public List<ChatSource> getSources() {
175         return sources;
176     }
177 
178     /**
179      * Sets the list of sources referenced in the message.
180      *
181      * @param sources the list of sources
182      */
183     public void setSources(final List<ChatSource> sources) {
184         this.sources = sources;
185     }
186 
187     /**
188      * Adds a source to the message.
189      *
190      * @param source the source to add
191      */
192     public void addSource(final ChatSource source) {
193         if (sources == null) {
194             sources = new ArrayList<>();
195         }
196         sources.add(source);
197     }
198 
199     /**
200      * Checks if this is a user message.
201      *
202      * @return true if this is a user message
203      */
204     public boolean isUser() {
205         return ROLE_USER.equals(role);
206     }
207 
208     /**
209      * Checks if this is an assistant message.
210      *
211      * @return true if this is an assistant message
212      */
213     public boolean isAssistant() {
214         return ROLE_ASSISTANT.equals(role);
215     }
216 
217     /**
218      * Gets the HTML-rendered content.
219      *
220      * @return the HTML content, or null if not rendered
221      */
222     public String getHtmlContent() {
223         return htmlContent;
224     }
225 
226     /**
227      * Sets the HTML-rendered content.
228      *
229      * @param htmlContent the HTML content
230      */
231     public void setHtmlContent(final String htmlContent) {
232         this.htmlContent = htmlContent;
233     }
234 
235     /**
236      * Represents a source document referenced in the chat response.
237      */
238     public static class ChatSource implements Serializable {
239 
240         private static final long serialVersionUID = 1L;
241 
242         /** The index of this source in the result list. */
243         private int index;
244 
245         /** The title of the source document. */
246         private String title;
247 
248         /** The URL of the source document. */
249         private String url;
250 
251         /** The document ID. */
252         private String docId;
253 
254         /** A snippet from the source document. */
255         private String snippet;
256 
257         /** The ViewHelper-processed URL for display. */
258         private String urlLink;
259 
260         /** The go link URL for navigation with access control and click logging. */
261         private String goUrl;
262 
263         /**
264          * Default constructor.
265          */
266         public ChatSource() {
267         }
268 
269         /**
270          * Creates a new chat source from a document map.
271          *
272          * @param index the source index
273          * @param doc the document map containing source data
274          */
275         public ChatSource(final int index, final Map<String, Object> doc) {
276             this.index = index;
277             String titleValue = toStringOrNull(doc.get("title"));
278             if (titleValue == null || titleValue.isEmpty()) {
279                 titleValue = toStringOrNull(doc.get("content_title"));
280             }
281             this.title = titleValue;
282             this.url = toStringOrNull(doc.get("url"));
283             this.docId = toStringOrNull(doc.get("doc_id"));
284             this.snippet = toStringOrNull(doc.get("content_description"));
285             this.urlLink = toStringOrNull(doc.get("url_link"));
286         }
287 
288         private static String toStringOrNull(final Object value) {
289             if (value == null) {
290                 return null;
291             }
292             if (value instanceof String) {
293                 return (String) value;
294             }
295             return value.toString();
296         }
297 
298         /**
299          * Gets the source index.
300          *
301          * @return the source index
302          */
303         public int getIndex() {
304             return index;
305         }
306 
307         /**
308          * Sets the source index.
309          *
310          * @param index the source index
311          */
312         public void setIndex(final int index) {
313             this.index = index;
314         }
315 
316         /**
317          * Gets the source title.
318          *
319          * @return the source title
320          */
321         public String getTitle() {
322             return title;
323         }
324 
325         /**
326          * Sets the source title.
327          *
328          * @param title the source title
329          */
330         public void setTitle(final String title) {
331             this.title = title;
332         }
333 
334         /**
335          * Gets the source URL.
336          *
337          * @return the source URL
338          */
339         public String getUrl() {
340             return url;
341         }
342 
343         /**
344          * Sets the source URL.
345          *
346          * @param url the source URL
347          */
348         public void setUrl(final String url) {
349             this.url = url;
350         }
351 
352         /**
353          * Gets the document ID.
354          *
355          * @return the document ID
356          */
357         public String getDocId() {
358             return docId;
359         }
360 
361         /**
362          * Sets the document ID.
363          *
364          * @param docId the document ID
365          */
366         public void setDocId(final String docId) {
367             this.docId = docId;
368         }
369 
370         /**
371          * Gets the source snippet.
372          *
373          * @return the source snippet
374          */
375         public String getSnippet() {
376             return snippet;
377         }
378 
379         /**
380          * Sets the source snippet.
381          *
382          * @param snippet the source snippet
383          */
384         public void setSnippet(final String snippet) {
385             this.snippet = snippet;
386         }
387 
388         /**
389          * Gets the ViewHelper-processed URL for display.
390          *
391          * @return the URL link
392          */
393         public String getUrlLink() {
394             return urlLink;
395         }
396 
397         /**
398          * Sets the ViewHelper-processed URL for display.
399          *
400          * @param urlLink the URL link
401          */
402         public void setUrlLink(final String urlLink) {
403             this.urlLink = urlLink;
404         }
405 
406         /**
407          * Gets the go link URL for navigation.
408          *
409          * @return the go URL
410          */
411         public String getGoUrl() {
412             return goUrl;
413         }
414 
415         /**
416          * Sets the go link URL for navigation.
417          *
418          * @param goUrl the go URL
419          */
420         public void setGoUrl(final String goUrl) {
421             this.goUrl = goUrl;
422         }
423     }
424 }