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
2 changes: 1 addition & 1 deletion pom-dependency-tree.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ai.elimu:webapp:war:2.6.12-SNAPSHOT
ai.elimu:webapp:war:2.6.15-SNAPSHOT
+- ai.elimu:model:jar:model-2.0.97:compile
| \- com.google.code.gson:gson:jar:2.13.0:compile
| \- com.google.errorprone:error_prone_annotations:jar:2.37.0:compile
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/ai/elimu/entity/content/Word.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import java.util.stream.Collectors;

import lombok.Getter;
import lombok.Setter;

Expand Down Expand Up @@ -41,4 +43,12 @@ public class Word extends Content {
// @NotNull
@Enumerated(EnumType.STRING)
private SpellingConsistency spellingConsistency;

public String toString() {
String letters = "";
for (LetterSound letterSound : letterSounds) {
letters += letterSound.getLetters().stream().map(Letter::getText).collect(Collectors.joining());
}
return letters;
}
Comment on lines +47 to +53
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve toString() implementation for robustness and efficiency.

The current implementation has several issues that should be addressed:

  1. Null safety: No null checks for letterSounds or individual letterSound objects
  2. Inefficiency: String concatenation in a loop creates multiple intermediate objects
  3. Readability: No separators between letter groups may affect readability

Apply this diff to improve the implementation:

-  public String toString() {
-    String letters = "";
-    for (LetterSound letterSound : letterSounds) {
-      letters += letterSound.getLetters().stream().map(Letter::getText).collect(Collectors.joining());
-    }
-    return letters;
-  }
+  public String toString() {
+    if (letterSounds == null || letterSounds.isEmpty()) {
+      return "";
+    }
+    return letterSounds.stream()
+      .filter(letterSound -> letterSound != null && letterSound.getLetters() != null)
+      .map(letterSound -> letterSound.getLetters().stream()
+        .map(Letter::getText)
+        .collect(Collectors.joining()))
+      .collect(Collectors.joining());
+  }

This version:

  • Adds null safety checks
  • Uses streams throughout for better performance
  • Filters out null objects to prevent runtime exceptions
  • Maintains the same concatenation behavior while being more robust
🤖 Prompt for AI Agents
In src/main/java/ai/elimu/entity/content/Word.java around lines 47 to 53, the
toString() method lacks null checks for letterSounds and its elements, uses
inefficient string concatenation in a loop, and does not separate letter groups
for readability. To fix this, add null checks for letterSounds and each
letterSound, replace string concatenation with a StringBuilder or use streams to
join strings efficiently, filter out any null letterSound objects, and consider
adding a separator between letter groups to improve readability while preserving
the original concatenation logic.

}
10 changes: 5 additions & 5 deletions src/main/webapp/WEB-INF/jsp/content/word/create.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@
<i class="close material-icons">clear</i>
</a>
<a href="<spring:url value='/content/letter-sound/edit/${letterSound.id}' />">
" <c:forEach var="letter" items="${letterSound.letters}">
${letter.text}<c:out value=" " />
</c:forEach> "<br />
↓<br />
/ <c:forEach var="sound" items="${letterSound.sounds}">
${sound.valueIpa}<c:out value=" " />
</c:forEach> /
</c:forEach> /<br />
↓<br />
" <c:forEach var="letter" items="${letterSound.letters}">
${letter.text}<c:out value=" " />
</c:forEach> "
</a>
</div>
</c:forEach>
Expand Down
10 changes: 5 additions & 5 deletions src/main/webapp/WEB-INF/jsp/content/word/edit.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@
<i class="close material-icons">clear</i>
</a>
<a href="<spring:url value='/content/letter-sound/edit/${letterSound.id}' />">
" <c:forEach var="letter" items="${letterSound.letters}">
${letter.text}<c:out value=" " />
</c:forEach> "<br />
↓<br />
/ <c:forEach var="sound" items="${letterSound.sounds}">
${sound.valueIpa}<c:out value=" " />
</c:forEach> /
</c:forEach> /<br />
↓<br />
" <c:forEach var="letter" items="${letterSound.letters}">
${letter.text}<c:out value=" " />
</c:forEach> "
</a>
</div>
</c:forEach>
Expand Down
80 changes: 24 additions & 56 deletions src/main/webapp/WEB-INF/jsp/content/word/list.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -25,87 +25,55 @@
<table class="bordered highlight">
<thead>
<th>Frequency</th>
<th>Text</th>
<th>Letter-sound correspondences</th>
<%--<th>Grapheme-phoneme correspondence</th>--%>
<th>Word</th>
<th>Word type</th>
<th>Root word</th>
<th>Revision</th>
</thead>
<tbody>
<c:forEach var="word" items="${words}">
<tr>
<td>
${word.usageCount}<br />
${word.usageCount}
<div class="progress">
<div class="determinate" style="width: ${word.usageCount * 100 / maxUsageCount}%"></div>
</div>
</td>
<td style="font-size: 2em;">
<a name="${word.id}"></a>
<a class="editLink" href="<spring:url value='/content/word/edit/${word.id}' />">"<c:out value="${word.text}" />"</a>
</td>
<td style="font-size: 2em;">
<td>
<div style="float: right; text-align: right;">
<label>word.getText()</label>
<div style="font-size: 2em;">
"${word.text}"
</div>
</div>

<label>word.toString()</label>
<div style="font-size: 2em;">
<a class="editLink" href="<spring:url value='/content/word/edit/${word.id}' />">"${word}"</a>
</div>

<div id="letterSoundsContainer">
<label>Sound-to-letter correspondences</label><br />
<c:forEach var="letterSound" items="${word.letterSounds}">
<input name="letterSounds" type="hidden" value="${letterSound.id}" />
<div class="chip">
<a href="<spring:url value='/content/letter-sound/edit/${letterSound.id}' />">
" <c:forEach var="letter" items="${letterSound.letters}">
${letter.text}<c:out value=" " />
</c:forEach> "<br />
/ <c:forEach var="sound" items="${letterSound.sounds}">
${sound.valueIpa}<c:out value=" " />
</c:forEach> /
</c:forEach> /<br />
↓<br />
" <c:forEach var="letter" items="${letterSound.letters}">
${letter.text}<c:out value=" " />
</c:forEach> "
</a>
</div>
</c:forEach>
</div>
</td>
<%--
<td>
<c:choose>
<c:when test="${word.spellingConsistency == 'PERFECT'}">
<c:set var="spellingConsistencyColor" value="green lighten-1" />
</c:when>
<c:when test="${word.spellingConsistency == 'HIGHLY_PHONEMIC'}">
<c:set var="spellingConsistencyColor" value="green lighten-3" />
</c:when>
<c:when test="${word.spellingConsistency == 'PHONEMIC'}">
<c:set var="spellingConsistencyColor" value="yellow lighten-3" />
</c:when>
<c:when test="${word.spellingConsistency == 'NON_PHONEMIC'}">
<c:set var="spellingConsistencyColor" value="orange lighten-3" />
</c:when>
<c:when test="${word.spellingConsistency == 'HIGHLY_NON_PHONEMIC'}">
<c:set var="spellingConsistencyColor" value="red lighten-3" />
</c:when>
<c:otherwise>
<c:set var="spellingConsistencyColor" value="" />
</c:otherwise>
</c:choose>
<div class="chip ${spellingConsistencyColor}">
<c:choose>
<c:when test="${word.spellingConsistency == 'PERFECT'}">Perfect (100% correspondence)</c:when>
<c:when test="${word.spellingConsistency == 'HIGHLY_PHONEMIC'}">Highly phonemic (80%-99% correspondence)</c:when>
<c:when test="${word.spellingConsistency == 'PHONEMIC'}">Phonemic (60%-79% correspondence)</c:when>
<c:when test="${word.spellingConsistency == 'NON_PHONEMIC'}">Non-phonemic (40%-59% correspondence)</c:when>
<c:when test="${word.spellingConsistency == 'HIGHLY_NON_PHONEMIC'}">Highly non-phonemic (0%-39% correspondence)</c:when>
</c:choose>
${word.wordType}
<div style="font-size: 2em;">
<c:out value=" ${emojisByWordId[word.id]}" />
</div>
</td>
--%>
<td>
${word.wordType}<br />
<c:out value=" ${emojisByWordId[word.id]}" />
</td>
<td>
<c:if test="${not empty word.rootWord}">
<a href="<spring:url value='/content/word/edit/${word.rootWord.id}' />">
${word.rootWord.text}
</a> (${word.rootWord.wordType})
</c:if>
</td>
<td>
<p>#${word.revisionNumber}</p>
<p>
Expand Down