1   package ixa.kaflib;
2   
3   import javax.annotation.Nullable;
4   import java.io.Serializable;
5   import java.util.ArrayList;
6   import java.util.HashMap;
7   import java.util.List;
8   import java.util.Objects;
9   
10  /**
11   * Class for representing opinions.
12   */
13  public class Opinion implements Serializable {
14  
15      private static final long serialVersionUID = -6971847529645535297L;
16  
17      public enum Polarity {
18  
19          NEUTRAL, POSITIVE, NEGATIVE;
20  
21          public static Polarity forOpinion(final Opinion opinion) {
22              return forLabel(opinion == null || opinion.getOpinionExpression() == null ? null
23                      : opinion.getOpinionExpression().getPolarity());
24          }
25  
26          public static Polarity forExpression(final OpinionExpression expression) {
27              return forLabel(expression == null ? null : expression.getPolarity());
28          }
29  
30          public static Polarity forLabel(@Nullable final String string) {
31              if (string != null) {
32                  final String s = string.toLowerCase();
33                  if (s.contains("pos")) {
34                      return POSITIVE;
35                  } else if (s.contains("neg")) {
36                      return NEGATIVE;
37                  }
38              }
39              return NEUTRAL;
40          }
41  
42      }
43      
44      public static class OpinionHolder implements Serializable {
45  
46          /**
47           *
48           */
49          private static final long serialVersionUID = -956906026133317235L;
50          private String type;
51          private Span<Term> span;
52          private final List<ExternalRef> externalReferences;
53  
54          OpinionHolder(final Span<Term> span) {
55              this.span = span;
56              this.externalReferences = new ArrayList<ExternalRef>();
57          }
58  
59          OpinionHolder(final OpinionHolder oh, final HashMap<String, Term> terms) {
60              /* Copy span */
61              final Span<Term> span = oh.span;
62              final List<Term> targets = span.getTargets();
63              final List<Term> copiedTargets = new ArrayList<Term>();
64              for (final Term term : targets) {
65                  final Term copiedTerm = terms.get(term.getId());
66                  if (copiedTerm == null) {
67                      throw new IllegalStateException("Term not found when copying opinion_holder");
68                  }
69                  copiedTargets.add(copiedTerm);
70              }
71              if (span.hasHead()) {
72                  final Term copiedHead = terms.get(span.getHead().getId());
73                  this.span = new Span<Term>(copiedTargets, copiedHead);
74              } else {
75                  this.span = new Span<Term>(copiedTargets);
76              }
77              this.externalReferences = new ArrayList<ExternalRef>();
78              for (final ExternalRef externalRef : oh.getExternalRefs()) {
79                  this.externalReferences.add(new ExternalRef(externalRef));
80              }
81          }
82  
83          public boolean hasType() {
84              return this.type != null;
85          }
86  
87          public String getType() {
88              return this.type;
89          }
90  
91          public void setType(final String type) {
92              this.type = type;
93          }
94  
95          public List<Term> getTerms() {
96              return this.span.getTargets();
97          }
98  
99          public void addTerm(final Term term) {
100             this.span.addTarget(term);
101         }
102 
103         public void addTerm(final Term term, final boolean isHead) {
104             this.span.addTarget(term, isHead);
105         }
106 
107         public Span<Term> getSpan() {
108             return this.span;
109         }
110 
111         public void setSpan(final Span<Term> span) {
112             this.span = span;
113         }
114 
115         public ExternalRef getExternalRef(final String resource) {
116             for (final ExternalRef ref : this.externalReferences) {
117                 if (ref.getResource().equalsIgnoreCase(resource)) {
118                     return ref;
119                 }
120             }
121             return null;
122         }
123 
124         public List<ExternalRef> getExternalRefs() {
125             return this.externalReferences;
126         }
127 
128         public void addExternalRef(final ExternalRef externalRef) {
129             this.externalReferences.add(externalRef);
130         }
131 
132         public void addExternalRefs(final List<ExternalRef> externalRefs) {
133             this.externalReferences.addAll(externalRefs);
134         }
135 
136         @Override
137         public boolean equals(final Object object) {
138             if (object == this) {
139                 return true;
140             }
141             if (!(object instanceof OpinionTarget)) {
142                 return false;
143             }
144             final OpinionHolder other = (OpinionHolder) object;
145             return Objects.equals(this.span, other.span) && Objects.equals(this.type, other.type)
146                     && Objects.equals(this.externalReferences, other.externalReferences);
147         }
148 
149         @Override
150         public int hashCode() {
151             return Objects.hash(this.span, this.type, this.externalReferences);
152         }
153 
154         @Override
155         public String toString() {
156             return "Holder: " + this.span;
157         }
158 
159     }
160 
161     public static class OpinionTarget implements Serializable {
162 
163         /**
164          *
165          */
166         private static final long serialVersionUID = -9128844215615857214L;
167         private Span<Term> span;
168         private String type;
169         private final List<ExternalRef> externalReferences;
170 
171         OpinionTarget(final Span<Term> span) {
172             this.span = span;
173             this.externalReferences = new ArrayList<ExternalRef>();
174         }
175 
176         OpinionTarget(final OpinionTarget ot, final HashMap<String, Term> terms) {
177             /* Copy span */
178             final Span<Term> span = ot.span;
179             final List<Term> targets = span.getTargets();
180             final List<Term> copiedTargets = new ArrayList<Term>();
181             for (final Term term : targets) {
182                 final Term copiedTerm = terms.get(term.getId());
183                 if (copiedTerm == null) {
184                     throw new IllegalStateException("Term not found when copying opinion_target");
185                 }
186                 copiedTargets.add(copiedTerm);
187             }
188             if (span.hasHead()) {
189                 final Term copiedHead = terms.get(span.getHead().getId());
190                 this.span = new Span<Term>(copiedTargets, copiedHead);
191             } else {
192                 this.span = new Span<Term>(copiedTargets);
193             }
194             this.externalReferences = new ArrayList<ExternalRef>();
195             for (final ExternalRef externalRef : ot.getExternalRefs()) {
196                 this.externalReferences.add(new ExternalRef(externalRef));
197             }
198         }
199 
200         public boolean hasType() {
201             return this.type != null;
202         }
203 
204         public String getType() {
205             return this.type;
206         }
207 
208         public void setType(final String type) {
209             this.type = type;
210         }
211 
212         public List<Term> getTerms() {
213             return this.span.getTargets();
214         }
215 
216         public void addTerm(final Term term) {
217             this.span.addTarget(term);
218         }
219 
220         public void addTerm(final Term term, final boolean isHead) {
221             this.span.addTarget(term, isHead);
222         }
223 
224         public Span<Term> getSpan() {
225             return this.span;
226         }
227 
228         public void setSpan(final Span<Term> span) {
229             this.span = span;
230         }
231 
232         public ExternalRef getExternalRef(final String resource) {
233             for (final ExternalRef ref : this.externalReferences) {
234                 if (ref.getResource().equalsIgnoreCase(resource)) {
235                     return ref;
236                 }
237             }
238             return null;
239         }
240 
241         public List<ExternalRef> getExternalRefs() {
242             return this.externalReferences;
243         }
244 
245         public void addExternalRef(final ExternalRef externalRef) {
246             this.externalReferences.add(externalRef);
247         }
248 
249         public void addExternalRefs(final List<ExternalRef> externalRefs) {
250             this.externalReferences.addAll(externalRefs);
251         }
252 
253         @Override
254         public boolean equals(final Object object) {
255             if (object == this) {
256                 return true;
257             }
258             if (!(object instanceof OpinionTarget)) {
259                 return false;
260             }
261             final OpinionTarget other = (OpinionTarget) object;
262             return Objects.equals(this.span, other.span) && Objects.equals(this.type, other.type)
263                     && Objects.equals(this.externalReferences, other.externalReferences);
264         }
265 
266         @Override
267         public int hashCode() {
268             return Objects.hash(this.span, this.type, this.externalReferences);
269         }
270 
271         @Override
272         public String toString() {
273             return "Target: " + this.span;
274         }
275 
276     }
277 
278     public static class OpinionExpression implements Serializable {
279 
280         /**
281          *
282          */
283         private static final long serialVersionUID = 3404051215983026456L;
284 
285         /* Polarity (optional) */
286         private String polarity;
287 
288         /* Strength (optional) */
289         private String strength;
290 
291         /* Subjectivity (optional) */
292         private String subjectivity;
293 
294         /* Sentiment semantic type (optional) */
295         private String sentimentSemanticType;
296 
297         /* Sentiment product feature (optional) */
298         private String sentimentProductFeature;
299 
300         private Span<Term> span;
301 
302         private final List<ExternalRef> externalReferences;
303 
304         OpinionExpression(final Span<Term> span) {
305             this.span = span;
306             this.externalReferences = new ArrayList<ExternalRef>();
307         }
308 
309         OpinionExpression(final OpinionExpression oe, final HashMap<String, Term> terms) {
310             this.polarity = oe.polarity;
311             this.strength = oe.strength;
312             this.subjectivity = oe.subjectivity;
313             this.sentimentSemanticType = oe.sentimentSemanticType;
314             this.sentimentProductFeature = oe.sentimentProductFeature;
315             /* Copy span */
316             final Span<Term> span = oe.span;
317             final List<Term> targets = span.getTargets();
318             final List<Term> copiedTargets = new ArrayList<Term>();
319             for (final Term term : targets) {
320                 final Term copiedTerm = terms.get(term.getId());
321                 if (copiedTerm == null) {
322                     throw new IllegalStateException(
323                             "Term not found when copying opinion_expression");
324                 }
325                 copiedTargets.add(copiedTerm);
326             }
327             if (span.hasHead()) {
328                 final Term copiedHead = terms.get(span.getHead().getId());
329                 this.span = new Span<Term>(copiedTargets, copiedHead);
330             } else {
331                 this.span = new Span<Term>(copiedTargets);
332             }
333             this.externalReferences = new ArrayList<ExternalRef>();
334             for (final ExternalRef externalRef : oe.getExternalRefs()) {
335                 this.externalReferences.add(new ExternalRef(externalRef));
336             }
337         }
338 
339         public boolean hasPolarity() {
340             return this.polarity != null;
341         }
342 
343         public String getPolarity() {
344             return this.polarity;
345         }
346 
347         public void setPolarity(final String polarity) {
348             this.polarity = polarity;
349         }
350 
351         public boolean hasStrength() {
352             return this.strength != null;
353         }
354 
355         public String getStrength() {
356             return this.strength;
357         }
358 
359         public void setStrength(final String strength) {
360             this.strength = strength;
361         }
362 
363         public boolean hasSubjectivity() {
364             return this.subjectivity != null;
365         }
366 
367         public String getSubjectivity() {
368             return this.subjectivity;
369         }
370 
371         public void setSubjectivity(final String subjectivity) {
372             this.subjectivity = subjectivity;
373         }
374 
375         public boolean hasSentimentSemanticType() {
376             return this.sentimentSemanticType != null;
377         }
378 
379         public String getSentimentSemanticType() {
380             return this.sentimentSemanticType;
381         }
382 
383         public void setSentimentSemanticType(final String sentimentSemanticType) {
384             this.sentimentSemanticType = sentimentSemanticType;
385         }
386 
387         public boolean hasSentimentProductFeature() {
388             return this.sentimentProductFeature != null;
389         }
390 
391         public String getSentimentProductFeature() {
392             return this.sentimentProductFeature;
393         }
394 
395         public void setSentimentProductFeature(final String sentimentProductFeature) {
396             this.sentimentProductFeature = sentimentProductFeature;
397         }
398 
399         public List<Term> getTerms() {
400             return this.span.getTargets();
401         }
402 
403         public void addTerm(final Term term) {
404             this.span.addTarget(term);
405         }
406 
407         public void addTerm(final Term term, final boolean isHead) {
408             this.span.addTarget(term, isHead);
409         }
410 
411         public Span<Term> getSpan() {
412             return this.span;
413         }
414 
415         public void setSpan(final Span<Term> span) {
416             this.span = span;
417         }
418 
419         public ExternalRef getExternalRef(final String resource) {
420             for (final ExternalRef ref : this.externalReferences) {
421                 if (ref.getResource().equalsIgnoreCase(resource)) {
422                     return ref;
423                 }
424             }
425             return null;
426         }
427 
428         public List<ExternalRef> getExternalRefs() {
429             return this.externalReferences;
430         }
431 
432         public void addExternalRef(final ExternalRef externalRef) {
433             this.externalReferences.add(externalRef);
434         }
435 
436         public void addExternalRefs(final List<ExternalRef> externalRefs) {
437             this.externalReferences.addAll(externalRefs);
438         }
439 
440         @Override
441         public boolean equals(final Object object) {
442             if (object == this) {
443                 return true;
444             }
445             if (!(object instanceof OpinionExpression)) {
446                 return false;
447             }
448             final OpinionExpression other = (OpinionExpression) object;
449             return Objects.equals(this.polarity, other.polarity)
450                     && Objects.equals(this.strength, other.strength)
451                     && Objects.equals(this.subjectivity, other.subjectivity)
452                     && Objects.equals(this.sentimentSemanticType, other.sentimentSemanticType)
453                     && Objects.equals(this.sentimentProductFeature, other.sentimentProductFeature)
454                     && Objects.equals(this.span, other.span)
455                     && Objects.equals(this.externalReferences, other.externalReferences);
456         }
457 
458         @Override
459         public int hashCode() {
460             return Objects.hash(this.polarity, this.strength, this.subjectivity,
461                     this.sentimentSemanticType, this.sentimentProductFeature, this.span,
462                     this.externalReferences);
463         }
464 
465         @Override
466         public String toString() {
467             return "Expression " + this.polarity + ": " + this.span;
468         }
469 
470     }
471 
472     private String id;
473     private OpinionHolder opinionHolder;
474     private OpinionTarget opinionTarget;
475     private OpinionExpression opinionExpression;
476     private String label;
477     private final List<ExternalRef> externalReferences;
478 
479     public String getLabel() {
480         return this.label;
481     }
482 
483     public void setLabel(final String label) {
484         this.label = label;
485     }
486 
487     Opinion(final String id) {
488         this.id = id;
489         this.externalReferences = new ArrayList<ExternalRef>();
490     }
491 
492     Opinion(final Opinion opinion, final HashMap<String, Term> terms) {
493         this.id = opinion.id;
494         if (opinion.opinionHolder != null) {
495             this.opinionHolder = new OpinionHolder(opinion.opinionHolder, terms);
496         }
497         if (opinion.opinionTarget != null) {
498             this.opinionTarget = new OpinionTarget(opinion.opinionTarget, terms);
499         }
500         if (opinion.opinionExpression != null) {
501             this.opinionExpression = new OpinionExpression(opinion.opinionExpression, terms);
502         }
503         this.externalReferences = new ArrayList<ExternalRef>();
504         for (final ExternalRef externalRef : opinion.getExternalRefs()) {
505             this.externalReferences.add(new ExternalRef(externalRef));
506         }
507     }
508 
509     public String getId() {
510         return this.id;
511     }
512 
513     void setId(final String id) {
514         this.id = id;
515     }
516 
517     public String getPolarity() {
518         return this.opinionExpression == null ? null : this.opinionExpression.getPolarity();
519     }
520 
521     public void setPolarity(final String polarity) {
522         if (this.opinionExpression != null) {
523             this.opinionExpression.setPolarity(polarity);
524         } else if (polarity != null) {
525             this.opinionExpression = new Opinion.OpinionExpression(KAFDocument.newTermSpan());
526             this.opinionExpression.setPolarity(polarity);
527         }
528     }
529 
530     public Span<Term> getExpressionSpan() {
531         return this.opinionExpression == null ? null : this.opinionExpression.getSpan();
532     }
533 
534     public void setExpressionSpan(final Span<Term> expressionSpan) {
535         if (this.opinionExpression != null) {
536             this.opinionExpression.setSpan(expressionSpan != null ? expressionSpan //
537                     : KAFDocument.newTermSpan());
538         } else if (expressionSpan != null && !expressionSpan.isEmpty()) {
539             this.opinionExpression = new Opinion.OpinionExpression(expressionSpan);
540         }
541     }
542 
543     public Span<Term> getHolderSpan() {
544         return this.opinionHolder == null ? null : this.opinionHolder.getSpan();
545     }
546 
547     public void setHolderSpan(final Span<Term> holderSpan) {
548         if (holderSpan == null || holderSpan.isEmpty()) {
549             this.opinionHolder = null;
550         } else if (this.opinionHolder == null) {
551             this.opinionHolder = new Opinion.OpinionHolder(holderSpan);
552         } else {
553             this.opinionHolder.setSpan(holderSpan);
554         }
555     }
556 
557     public Span<Term> getTargetSpan() {
558         return this.opinionTarget == null ? null : this.opinionTarget.getSpan();
559     }
560 
561     public void setTargetSpan(final Span<Term> targetSpan) {
562         if (targetSpan == null || targetSpan.isEmpty()) {
563             this.opinionTarget = null;
564         } else if (this.opinionTarget == null) {
565             this.opinionTarget = new Opinion.OpinionTarget(targetSpan);
566         } else {
567             this.opinionTarget.setSpan(targetSpan);
568         }
569     }
570 
571     public OpinionHolder getOpinionHolder() {
572         return this.opinionHolder;
573     }
574 
575     public OpinionTarget getOpinionTarget() {
576         return this.opinionTarget;
577     }
578 
579     public OpinionExpression getOpinionExpression() {
580         return this.opinionExpression;
581     }
582 
583     public OpinionHolder createOpinionHolder(final Span<Term> span) {
584         this.opinionHolder = new Opinion.OpinionHolder(span);
585         return this.opinionHolder;
586     }
587 
588     public OpinionTarget createOpinionTarget(final Span<Term> span) {
589         this.opinionTarget = new Opinion.OpinionTarget(span);
590         return this.opinionTarget;
591     }
592 
593     public OpinionExpression createOpinionExpression(final Span<Term> span) {
594         this.opinionExpression = new Opinion.OpinionExpression(span);
595         return this.opinionExpression;
596     }
597 
598     public OpinionHolder removeOpinionHolder() {
599         final OpinionHolder result = this.opinionHolder;
600         this.opinionHolder = null;
601         return result;
602     }
603 
604     public OpinionTarget removeOpinionTarget() {
605         final OpinionTarget result = this.opinionTarget;
606         this.opinionTarget = null;
607         return result;
608     }
609 
610     public OpinionExpression removeOpinionExpression() {
611         final OpinionExpression result = this.opinionExpression;
612         this.opinionExpression = null;
613         return result;
614     }
615 
616     public String getSpanStr(final Span<Term> span) {
617         String str = "";
618         for (final Term term : span.getTargets()) {
619             if (!str.isEmpty()) {
620                 str += " ";
621             }
622             str += term.getStr();
623         }
624         return str;
625     }
626 
627     public String getStr() {
628         return getSpanStr(getOpinionExpression().getSpan());
629     }
630 
631     public ExternalRef getExternalRef(final String resource) {
632         for (final ExternalRef ref : this.externalReferences) {
633             if (ref.getResource().equalsIgnoreCase(resource)) {
634                 return ref;
635             }
636         }
637         return null;
638     }
639 
640     public List<ExternalRef> getExternalRefs() {
641         return this.externalReferences;
642     }
643 
644     public void addExternalRef(final ExternalRef externalRef) {
645         this.externalReferences.add(externalRef);
646     }
647 
648     public void addExternalRefs(final List<ExternalRef> externalRefs) {
649         this.externalReferences.addAll(externalRefs);
650     }
651 
652 }