1   package eu.fbk.dkm.pikes.raid;
2   
3   import com.google.common.base.Objects;
4   import com.google.common.collect.ImmutableSet;
5   import com.google.common.collect.Iterables;
6   import com.google.common.collect.Lists;
7   import eu.fbk.dkm.pikes.resources.NAFUtils;
8   import ixa.kaflib.KAFDocument;
9   import ixa.kaflib.Opinion;
10  import ixa.kaflib.Opinion.OpinionExpression;
11  import ixa.kaflib.Opinion.OpinionHolder;
12  import ixa.kaflib.Opinion.OpinionTarget;
13  import ixa.kaflib.Opinion.Polarity;
14  import ixa.kaflib.Span;
15  import ixa.kaflib.Term;
16  
17  import javax.annotation.Nullable;
18  import java.util.List;
19  import java.util.Set;
20  
21  public final class Opinions {
22  
23      public static Set<Term> heads(final KAFDocument document, final Span<Term> span,
24              final Component component) {
25  
26          if (span == null || span.isEmpty()) {
27              return ImmutableSet.of();
28          }
29          return NAFUtils.extractHeads(document, null, span.getTargets(),
30                  NAFUtils.matchExtendedPos(document, component.getHeadPos()));
31      }
32  
33      public static boolean deduplicate(final KAFDocument document, final Iterable<Opinion> opinions) {
34          boolean modified = false;
35          final List<Opinion> seen = Lists.newArrayList();
36          outer: for (final Opinion o : opinions) {
37              for (final Opinion s : seen) {
38                  if (Objects.equal(o.getLabel(), s.getLabel())
39                          && Objects.equal(o.getPolarity(), s.getPolarity())
40                          && sameSpan(o.getExpressionSpan(), s.getExpressionSpan())
41                          && sameSpan(o.getHolderSpan(), s.getHolderSpan())
42                          && sameSpan(o.getTargetSpan(), s.getTargetSpan())) {
43                      document.removeAnnotation(o);
44                      modified = true;
45                      continue outer;
46                  }
47              }
48              seen.add(o);
49          }
50          return modified;
51      }
52  
53      private static boolean sameSpan(final Span<Term> span1, final Span<Term> span2) {
54          return span1 == null
55                  && span2 == null
56                  || span1 != null
57                  && span2 != null
58                  && ImmutableSet.copyOf(span1.getTargets()).equals(
59                          ImmutableSet.copyOf(span2.getTargets()));
60      }
61  
62      public static List<Opinion> merge(final KAFDocument document,
63              final Iterable<Opinion> opinions, final Iterable<Component> components) {
64          // TODO
65          return null;
66      }
67  
68      public static List<Opinion> split(final KAFDocument document,
69              final Iterable<Opinion> opinions, final Iterable<Component> components) {
70          // TODO
71          return null;
72      }
73  
74      @Deprecated
75      public static List<Opinion> split(final KAFDocument document,
76              final Iterable<Opinion> inOpinions, @Nullable final String outLabel) {
77  
78          final List<Span<Term>> emptySpanList = Lists.newArrayList();
79          emptySpanList.add(null);
80  
81          final List<Opinion> outOpinions = Lists.newArrayList();
82          for (final Opinion inOpinion : inOpinions) {
83  
84              final OpinionExpression inExp = inOpinion.getOpinionExpression();
85              final OpinionHolder inHolder = inOpinion.getOpinionHolder();
86              final OpinionTarget inTarget = inOpinion.getOpinionTarget();
87  
88              final Set<Term> expHeads = heads(document, inOpinion.getExpressionSpan(),
89                      Component.EXPRESSION);
90  
91              if (!expHeads.isEmpty()) {
92                  final List<Span<Term>> expSpans = NAFUtils.splitSpan(document, inExp.getSpan(),
93                          expHeads);
94  
95                  final Set<Term> holderHeads = heads(document, inOpinion.getHolderSpan(),
96                          Component.HOLDER);
97                  final List<Span<Term>> holderSpans = holderHeads.isEmpty() ? emptySpanList //
98                          : NAFUtils.splitSpan(document, inHolder.getSpan(), holderHeads);
99  
100                 final Set<Term> targetHeads = heads(document, inOpinion.getTargetSpan(),
101                         Component.TARGET);
102                 final List<Span<Term>> targetSpans = targetHeads.isEmpty() ? emptySpanList
103                         : NAFUtils.splitSpan(document, inTarget.getSpan(), targetHeads);
104 
105                 for (final Span<Term> expSpan : expSpans) {
106                     for (final Span<Term> holderSpan : holderSpans) {
107                         for (final Span<Term> targetSpan : targetSpans) {
108                             final Opinion outOpinion = document.newOpinion();
109                             outOpinion.setLabel(outLabel);
110                             final OpinionExpression outExp = outOpinion
111                                     .createOpinionExpression(expSpan);
112                             outExp.setPolarity(inExp.getPolarity());
113                             outExp.setSentimentProductFeature(inExp.getSentimentProductFeature());
114                             outExp.setSentimentSemanticType(inExp.getSentimentSemanticType());
115                             outExp.setStrength(inExp.getStrength());
116                             outExp.setSubjectivity(inExp.getSubjectivity());
117                             if (holderSpan != null) {
118                                 outOpinion.createOpinionHolder(holderSpan).setType(
119                                         inOpinion.getOpinionHolder().getType());
120                             }
121                             if (targetSpan != null) {
122                                 outOpinion.createOpinionTarget(targetSpan).setType(
123                                         inOpinion.getOpinionTarget().getType());
124                             }
125                             outOpinions.add(outOpinion);
126                         }
127                     }
128                 }
129             }
130         }
131         return outOpinions;
132     }
133 
134     public static void retain(final Iterable<Opinion> opinions,
135             @Nullable final Opinion refOpinion, final Iterable<Component> components) {
136 
137         for (final Opinion opinion : opinions) {
138             final OpinionExpression expr = opinion.getOpinionExpression();
139             if (!Iterables.contains(components, Component.POLARITY)) {
140                 if (refOpinion == null || refOpinion.getOpinionExpression() == null) {
141                     expr.setPolarity(null);
142                     expr.setStrength(null);
143                     expr.setSentimentProductFeature(null);
144                     expr.setSentimentSemanticType(null);
145                     expr.setSubjectivity(null);
146                 } else {
147                     final OpinionExpression refExpr = refOpinion.getOpinionExpression();
148                     expr.setPolarity(refExpr.getPolarity());
149                     expr.setStrength(refExpr.getStrength());
150                     expr.setSentimentProductFeature(refExpr.getSentimentProductFeature());
151                     expr.setSentimentSemanticType(refExpr.getSentimentSemanticType());
152                     expr.setSubjectivity(refExpr.getSubjectivity());
153                 }
154             }
155             if (!Iterables.contains(components, Component.EXPRESSION)) {
156                 if (refOpinion == null || refOpinion.getOpinionExpression() == null) {
157                     expr.setSpan(KAFDocument.newTermSpan());
158                 } else {
159                     expr.setSpan(refOpinion.getOpinionExpression().getSpan());
160                 }
161             }
162             if (!Iterables.contains(components, Component.HOLDER)) {
163                 if (refOpinion == null || refOpinion.getOpinionHolder() == null) {
164                     opinion.removeOpinionHolder();
165                 } else {
166                     opinion.createOpinionHolder(refOpinion.getOpinionHolder().getSpan()).setType(
167                             refOpinion.getOpinionHolder().getType());
168                 }
169             }
170             if (!Iterables.contains(components, Component.TARGET)) {
171                 if (refOpinion == null || refOpinion.getOpinionTarget() == null) {
172                     opinion.removeOpinionTarget();
173                 } else {
174                     opinion.createOpinionTarget(refOpinion.getOpinionTarget().getSpan()).setType(
175                             refOpinion.getOpinionTarget().getType());
176                 }
177             }
178         }
179     }
180 
181     public static List<Opinion> create(final KAFDocument document, final Span<Term> expression,
182             final Iterable<Span<Term>> holders, final Iterable<Span<Term>> targets,
183             final Polarity polarity) {
184 
185         final int numHolders = Iterables.size(holders);
186         final int numTargets = Iterables.size(targets);
187 
188         final List<Opinion> opinions = Lists.newArrayList();
189         for (final Span<Term> holder : holders) {
190             for (final Span<Term> target : targets) {
191 
192                 // Discard wrong holder / target combinations
193                 if (holder == null && numHolders > 1 || target == null && numTargets > 1) {
194                     continue;
195                 }
196 
197                 // Create the opinion and its expression
198                 final Opinion opinion = document.createOpinion();
199                 final OpinionExpression expr = opinion.createOpinionExpression(expression);
200 
201                 // Assign the polarity, if available
202                 if (polarity == Polarity.NEUTRAL) {
203                     expr.setPolarity("neutral");
204                 } else if (polarity == Polarity.NEGATIVE) {
205                     expr.setPolarity("negative");
206                 } else if (polarity == Polarity.POSITIVE) {
207                     expr.setPolarity("positive");
208                 }
209 
210                 // Assign the holder, if available
211                 if (holder != null) {
212                     opinion.createOpinionHolder(holder);
213                 }
214 
215                 // Assign the target, if available
216                 if (target != null) {
217                     opinion.createOpinionTarget(target);
218                 }
219 
220                 // Store the opinion
221                 opinions.add(opinion);
222             }
223         }
224         return opinions;
225     }
226 
227 }