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.dict.synonym;
17  
18  import java.util.Arrays;
19  import java.util.Objects;
20  
21  import org.apache.commons.lang3.StringUtils;
22  import org.codelibs.core.collection.ArrayUtil;
23  import org.codelibs.core.lang.StringUtil;
24  import org.codelibs.fess.dict.DictionaryItem;
25  
26  /**
27   * Represents an item in a synonym dictionary.
28   * This class stores a set of input words and their corresponding output synonyms.
29   * It also tracks updated values for the item.
30   */
31  public class SynonymItem extends DictionaryItem {
32      /** The original input words. */
33      private final String[] inputs;
34  
35      /** The original output synonyms. */
36      private final String[] outputs;
37  
38      /** The new input words, if updated. */
39      private String[] newInputs;
40  
41      /** The new output synonyms, if updated. */
42      private String[] newOutputs;
43  
44      /**
45       * Constructs a new synonym item.
46       *
47       * @param id      The unique identifier of the item.
48       * @param inputs  The input words.
49       * @param outputs The output synonyms.
50       */
51      public SynonymItem(final long id, final String[] inputs, final String[] outputs) {
52          this.id = id;
53          this.inputs = inputs;
54          this.outputs = outputs;
55  
56          if (id == 0) {
57              // create
58              newInputs = inputs;
59              newOutputs = outputs;
60          }
61      }
62  
63      /**
64       * Gets the new input words.
65       * Returns a defensive copy to prevent external modification.
66       *
67       * @return The new input words (defensive copy).
68       */
69      public String[] getNewInputs() {
70          return newInputs == null ? null : newInputs.clone();
71      }
72  
73      /**
74       * Sets the new input words.
75       *
76       * @param newInputs The new input words.
77       */
78      public void setNewInputs(final String[] newInputs) {
79          this.newInputs = newInputs;
80      }
81  
82      /**
83       * Gets the new output synonyms.
84       * Returns a defensive copy to prevent external modification.
85       *
86       * @return The new output synonyms (defensive copy).
87       */
88      public String[] getNewOutputs() {
89          return newOutputs == null ? null : newOutputs.clone();
90      }
91  
92      /**
93       * Sets the new output synonyms.
94       *
95       * @param newOutputs The new output synonyms.
96       */
97      public void setNewOutputs(final String[] newOutputs) {
98          this.newOutputs = newOutputs;
99      }
100 
101     /**
102      * Gets the original input words.
103      * Returns a defensive copy to prevent external modification.
104      *
105      * @return The original input words (defensive copy).
106      */
107     public String[] getInputs() {
108         return inputs == null ? null : inputs.clone();
109     }
110 
111     /**
112      * Gets the input words as a newline-separated string.
113      *
114      * @return The input words as a string.
115      */
116     public String getInputsValue() {
117         if (inputs == null) {
118             return StringUtil.EMPTY;
119         }
120         return String.join("\n", inputs);
121     }
122 
123     /**
124      * Gets the original output synonyms.
125      * Returns a defensive copy to prevent external modification.
126      *
127      * @return The original output synonyms (defensive copy).
128      */
129     public String[] getOutputs() {
130         return outputs == null ? null : outputs.clone();
131     }
132 
133     /**
134      * Gets the output synonyms as a newline-separated string.
135      *
136      * @return The output synonyms as a string.
137      */
138     public String getOutputsValue() {
139         if (outputs == null) {
140             return StringUtil.EMPTY;
141         }
142         return String.join("\n", outputs);
143     }
144 
145     /**
146      * Checks if the item has been updated.
147      *
148      * @return true if the item has been updated, false otherwise.
149      */
150     public boolean isUpdated() {
151         return newInputs != null && newOutputs != null;
152     }
153 
154     /**
155      * Checks if the item has been marked for deletion.
156      *
157      * @return true if the item is marked for deletion, false otherwise.
158      */
159     public boolean isDeleted() {
160         return isUpdated() && newInputs.length == 0;
161     }
162 
163     @Override
164     public int hashCode() {
165         return Objects.hash(Arrays.hashCode(inputs), Arrays.hashCode(outputs));
166     }
167 
168     @Override
169     public boolean equals(final Object obj) {
170         if (this == obj) {
171             return true;
172         }
173         if (obj == null || getClass() != obj.getClass()) {
174             return false;
175         }
176         final SynonymItem other = (SynonymItem) obj;
177         if (!ArrayUtil.equalsIgnoreSequence(inputs, other.inputs) || !ArrayUtil.equalsIgnoreSequence(outputs, other.outputs)) {
178             return false;
179         }
180         return true;
181     }
182 
183     @Override
184     public String toString() {
185         return "SynonymItem [id=" + id + ", inputs=" + Arrays.toString(inputs) + ", outputs=" + Arrays.toString(outputs) + ", newInputs="
186                 + Arrays.toString(newInputs) + ", newOutputs=" + Arrays.toString(newOutputs) + "]";
187     }
188 
189     /**
190      * Converts the item to a string representation for writing to a file.
191      *
192      * @return A string in the format "input1,input2=>output1,output2".
193      */
194     public String toLineString() {
195         if (isUpdated()) {
196             if (Arrays.equals(newInputs, newOutputs)) {
197                 return StringUtils.join(newInputs, ",");
198             }
199             return StringUtils.join(newInputs, ",") + "=>" + StringUtils.join(newOutputs, ",");
200         }
201         if (Arrays.equals(inputs, outputs)) {
202             return StringUtils.join(inputs, ",");
203         }
204         return StringUtils.join(inputs, ",") + "=>" + StringUtils.join(outputs, ",");
205     }
206 
207 }