1   package eu.fbk.dkm.premon.premonitor;
2   
3   import com.google.common.io.Files;
4   import eu.fbk.dkm.premon.util.URITreeSet;
5   import eu.fbk.dkm.premon.vocab.*;
6   import org.joox.JOOX;
7   import org.joox.Match;
8   import org.openrdf.model.URI;
9   import org.openrdf.model.vocabulary.RDF;
10  import org.openrdf.model.vocabulary.RDFS;
11  import org.openrdf.rio.RDFHandler;
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  import org.w3c.dom.Document;
15  import org.w3c.dom.Element;
16  import org.w3c.dom.Node;
17  import org.w3c.dom.NodeList;
18  
19  import javax.annotation.Nullable;
20  import javax.xml.parsers.DocumentBuilderFactory;
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.*;
24  import java.util.regex.Matcher;
25  import java.util.regex.Pattern;
26  
27  /*
28   * Problems on version 3.2b - Apparently useless examples.desktop and localmachine files -
29   * pronounce-29.3.1 has no xml extension - sound_emission-32.2.xml.bckup has no xml extension
30   */
31  
32  public class VerbnetConverter extends Converter {
33  
34      private static final Logger LOGGER = LoggerFactory.getLogger(VerbnetConverter.class);
35      private static final Pattern VN_PATTERN = Pattern.compile("([^-]+)-(.*)");
36      private static final Pattern WN_PATTERN = Pattern.compile("#([^#]+)$");
37      private static final String LINK_PATTERN = "http://verbs.colorado.edu/verb-index/vn/%s.php";
38  
39      private static final String DEFAULT_RESTRICTION_SUFFIX = "srs";
40      private static final String DEFAULT_FRAME_SUFFIX = "frame";
41      private static final String DEFAULT_EXAMPLE_SUFFIX = "ex";
42      private static final String DEFAULT_SYNITEM_SUFFIX = "SynItem";
43      //    private static final String DEFAULT_PRED_SUFFIX = "pred";
44      //    private static final String DEFAULT_ARG_SUFFIX = "arg";
45  
46      ArrayList<String> pbLinks = new ArrayList<>();
47  
48      public VerbnetConverter(final File path, final RDFHandler sink, final Properties properties,
49              final Map<String, URI> wnInfo) {
50          super(path, properties.getProperty("source"), sink, properties, properties
51                  .getProperty("language"), wnInfo);
52  
53          addLinks(this.pbLinks, properties.getProperty("linkpb"));
54          LOGGER.info("Links to: {}", this.pbLinks.toString());
55          LOGGER.info("Starting dataset: {}", this.prefix);
56      }
57  
58      @Override
59      public void convert() throws IOException {
60  
61          addMetaToSink();
62  
63          final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
64  
65          for (final File file : Files.fileTreeTraverser().preOrderTraversal(this.path)) {
66              if (!file.isDirectory() && file.getName().endsWith(".xml")) {
67                  LOGGER.debug("Processing {} ...", file);
68  
69                  try {
70                      final Document document = dbf.newDocumentBuilder().parse(file);
71                      final Match vnClass = JOOX.$(document.getElementsByTagName("VNCLASS"));
72  
73                      for (final Element thisClass : vnClass) {
74  
75                          // todo: Remove it!
76                          //                        String id = thisClass.getAttribute("ID");
77                          //                        if (!id.equals("admire-31.2")) {
78                          //                            continue;
79                          //                        }
80  
81                          addClassToSink(thisClass, null, null, null);
82  
83                      }
84  
85                  } catch (final Exception ex) {
86                      throw new IOException(ex);
87                  }
88              }
89          }
90  
91      }
92  
93      private void addClassToSink(final Element thisClass, @Nullable final URI superClass,
94              @Nullable final HashMap<String, Element> themRolesElements,
95              @Nullable final HashSet<URI> framesElements) {
96          final String id = thisClass.getAttribute("ID");
97  
98          final Matcher matcher = VN_PATTERN.matcher(id);
99          if (!matcher.find()) {
100             LOGGER.error("Class ID {} does not match", id);
101             return;
102         }
103 
104         // todo: Are we sure?
105         final String type = "v";
106 
107         final URI rolesetURI = uriForRoleset(id);
108         if (superClass == null) {
109             addStatementToSink(rolesetURI, RDFS.SEEALSO, getExternalLink(id));
110         } else {
111             addStatementToSink(rolesetURI, PMOVN.SUBCLASS_OF, superClass);
112         }
113 
114         addStatementToSink(rolesetURI, RDF.TYPE, PMOVN.VERB_CLASS);
115         addStatementToSink(rolesetURI, RDFS.LABEL, id, false);
116 
117         Match elements;
118         final HashMap<String, URI> lemmas = new HashMap<>();
119 
120         elements = JOOX.$(thisClass).xpath("MEMBERS/MEMBER");
121         for (final Element member : elements) {
122             String uriLemma = member.getAttribute("name");
123             uriLemma = uriLemma.replaceAll("_", "+");
124             final String goodLemma = uriLemma.replaceAll("\\+", " ");
125 
126             final String groupingString = member.getAttribute("grouping");
127             final String wnString = member.getAttribute("wn");
128 
129             final URI lexicalEntryURI = addLexicalEntry(goodLemma, uriLemma, null, null, "v",
130                     getLexicon());
131             lemmas.put(uriLemma, lexicalEntryURI);
132             addStatementToSink(lexicalEntryURI, ONTOLEX.EVOKES, rolesetURI);
133 
134             final URI conceptualizationURI = uriForConceptualization(uriLemma, type, id);
135             addStatementToSink(conceptualizationURI, RDF.TYPE, PMO.CONCEPTUALIZATION);
136             addStatementToSink(conceptualizationURI, PMO.EVOKING_ENTRY, lexicalEntryURI);
137             addStatementToSink(conceptualizationURI, PMO.EVOKED_CONCEPT, rolesetURI);
138 
139             final TreeSet<URI> mapping = new URITreeSet();
140             mapping.add(conceptualizationURI);
141 
142             if (groupingString != null && groupingString.trim().length() > 0) {
143                 final String[] groupings = groupingString.trim().split("\\s+");
144                 for (final String grouping : groupings) {
145                     for (final String pbLink : this.pbLinks) {
146                         if (pbLink.length() == 0) {
147                             continue;
148                         }
149 
150                         final URI pbRolesetURI = uriForRoleset(grouping, pbLink);
151                         final URI pbConceptualizationURI = uriForConceptualizationWithPrefix(
152                                 uriLemma, "v", grouping, pbLink);
153 
154                         addStatementToSink(pbConceptualizationURI, RDF.TYPE, PMO.CONCEPTUALIZATION);
155                         // addStatementToSink(pbConceptualizationURI, PMO.EVOKING_ENTRY, lexicalEntryURI);
156                         // addStatementToSink(pbConceptualizationURI, PMO.EVOKED_CONCEPT, pbRolesetURI);
157 
158                         //                        addStatementToSink(conceptualizationURI, SKOS.CLOSE_MATCH, pbConceptualizationURI);
159                         //                        addStatementToSink(pbConceptualizationURI, SKOS.CLOSE_MATCH, conceptualizationURI);
160                         mapping.add(pbConceptualizationURI);
161                     }
162                 }
163             }
164 
165             if (wnString != null && this.wnInfo.size() > 0) {
166                 final String[] wns = wnString.split("\\s+");
167 
168                 for (String wn : wns) {
169 
170                     wn = wn.trim();
171 
172                     if (wn.length() == 0) {
173                         continue;
174                     }
175 
176                     boolean questionMark = false;
177                     if (wn.startsWith("?")) {
178                         //                        LOGGER.warn("The wn {} starts with ?", wn);
179                         questionMark = true;
180                         wn = wn.substring(1);
181                     }
182 
183                     final URI wnURI = this.wnInfo.get(wn);
184 
185                     if (wnURI == null) {
186                         LOGGER.warn("No wnURI found for {}", wn);
187                         continue;
188                     }
189 
190                     String lemma = wn.substring(0, wn.indexOf('%'));
191                     final URI reference = this.wnInfo.get(wnURI.toString() + "|" + lemma);
192 
193                     if (reference == null) {
194                         LOGGER.warn("No reference found for {} / {}", wnURI.toString(), lemma);
195                         continue;
196                     }
197 
198                     final Matcher m = WN_PATTERN.matcher(reference.toString());
199                     if (!m.find()) {
200                         continue;
201                     }
202 
203                     final URI wnConceptualizationURI = uriForConceptualizationWithPrefix(uriLemma,
204                             "v", wnURI.toString().replace(WN_NAMESPACE,""), "wn31");
205 
206                     addStatementToSink(wnConceptualizationURI, RDF.TYPE, PMO.CONCEPTUALIZATION);
207                     addStatementToSink(wnConceptualizationURI, PMO.EVOKING_ENTRY, lexicalEntryURI);
208                     addStatementToSink(wnConceptualizationURI, RDFS.SEEALSO, reference);
209                     addStatementToSink(wnConceptualizationURI, PMO.EVOKED_CONCEPT, wnURI);
210                     //                    addStatementToSink(conceptualizationURI, SKOS.CLOSE_MATCH, wnConceptualizationURI);
211                     //                    addStatementToSink(wnConceptualizationURI, SKOS.CLOSE_MATCH, conceptualizationURI);
212                     mapping.add(wnConceptualizationURI);
213 
214                     // todo: check this
215                     //                    if (questionMark) {
216                     //                        addStatementToSink(conceptualizationURI, SKOS.RELATED_MATCH, wnConceptualizationURI);
217                     //                        addStatementToSink(wnConceptualizationURI, SKOS.RELATED_MATCH, conceptualizationURI);
218                     //                    }
219                 }
220 
221             }
222 
223             // Added only whether there is more than one URI in the Set
224             if (mapping.size() >= 2) {
225                 addMappingToSink(null, mapping, DEFAULT_SENSE_SUFFIX, prefix);
226             }
227         }
228 
229         // Load thematic roles
230         HashMap<String, Element> thisThemRolesElements = new HashMap<>();
231         if (themRolesElements != null) {
232             thisThemRolesElements = new HashMap<>(themRolesElements);
233         }
234         elements = JOOX.$(thisClass).xpath("THEMROLES/THEMROLE");
235         for (final Element element : elements) {
236             final String argName = element.getAttribute("type");
237             thisThemRolesElements.put(argName, element);
238             final URI argumentURI = uriForArgument(id, argName);
239             addStatementToSink(rolesetURI, PMOVN.DEFINES_SEM_ROLE, argumentURI);
240         }
241 
242         for (final String argName : thisThemRolesElements.keySet()) {
243             final Element element = thisThemRolesElements.get(argName);
244 
245             final URI argumentURI = uriForArgument(id, argName);
246 
247             addStatementToSink(rolesetURI, PMO.SEM_ROLE, argumentURI);
248             addStatementToSink(argumentURI, RDF.TYPE, PMOVN.SEMANTIC_ROLE);
249             addStatementToSink(argumentURI, PMOVN.THEMATIC_ROLE_P, PMOVN.lookup(PMOVN.THEMATIC_ROLE_C, argName));
250             //    for (final String lemma : lemmas.keySet()) {
251             //        final URI lemmaURI = lemmas.get(lemma);
252             //        addStatementToSink(lemmaURI, ONTOLEX.EVOKES, argumentURI);
253             //
254             //        final URI conceptualizationURI = uriForConceptualization(lemma, "v",
255             //                argPart(id, argName, ""));
256             //        addStatementToSink(conceptualizationURI, RDF.TYPE, PMO.CONCEPTUALIZATION);
257             //        addStatementToSink(conceptualizationURI, PMO.EVOKING_ENTRY, lemmaURI);
258             //        addStatementToSink(conceptualizationURI, PMO.EVOKED_CONCEPT, argumentURI);
259             //    }
260 
261             addRestrictions("SELRESTRS", "SELRESTR", argumentURI, element, "srs",
262                     PMOVN.ROLE_SELECTIONAL_RESTRICTION, PMOVN.ROLE_RESTRICTION_PROPERTY);
263         }
264 
265         elements = JOOX.$(thisClass).xpath("FRAMES/FRAME");
266 
267         final HashSet<URI> framesToPass = new HashSet<>();
268 
269         if (framesElements != null) {
270             for (final URI framesElement : framesElements) {
271                 addStatementToSink(rolesetURI, PMOVN.FRAME, framesElement);
272             }
273             framesToPass.addAll(framesElements);
274         }
275         final Set<URI> thisClassFrames = addFrames(elements, id);
276         framesToPass.addAll(thisClassFrames);
277 
278         elements = JOOX.$(thisClass).xpath("SUBCLASSES/VNSUBCLASS");
279         for (final Element element : elements) {
280             addClassToSink(element, rolesetURI, thisThemRolesElements, framesToPass);
281         }
282 
283     }
284 
285     private Set<URI> addFrames(final Match frames, final String id) {
286 
287         final Set<URI> frameURIs = new HashSet<>();
288 
289         final int totalSize = frames.size();
290         if (totalSize == 1) {
291             final URI frameURI = getFrameURI(id);
292             frameURIs.add(frameURI);
293             for (final Element element : frames) {
294                 addFrameToSink(id, frameURI, element);
295             }
296         }
297         if (totalSize > 1) {
298             int thisSize = 0;
299             for (final Element element : frames) {
300                 thisSize++;
301 
302                 final URI frameURI = getFrameURI(id, thisSize);
303                 frameURIs.add(frameURI);
304                 addFrameToSink(id, frameURI, element);
305             }
306         }
307 
308         return frameURIs;
309     }
310 
311     private void addRestrictions(final String label1, final String label2, final URI startingURI,
312             final Element element, final String suffix, final URI typeURI, final URI lookup) {
313         addRestrictions(label1, label2, startingURI, element, suffix, typeURI, lookup, null, null,
314                 null);
315     }
316 
317     private void addRestrictions(final String label1, final String label2, final URI startingURI,
318             final Element element, final String suffix, final URI typeURI, final URI lookup,
319             @Nullable final List<String> pieces, @Nullable final String sep1,
320             @Nullable final String sep2) {
321         final Match selrestrses = JOOX.$(element.getElementsByTagName(label1));
322         for (final Element selrestrse : selrestrses) {
323 
324             final Match selrestrs = JOOX.$(selrestrse.getElementsByTagName(label2));
325             final URI restrictionURI = uriForRestriction(startingURI, suffix);
326             if (selrestrs.size() == 1) {
327                 final URI voURI = PMOVN.lookup(lookup, selrestrs.get(0).getAttribute("type"));
328                 if (voURI == null) {
329                     LOGGER.error("Value not found: {}:{}", lookup,
330                             selrestrs.get(0).getAttribute("type"));
331                 }
332                 addStatementToSink(startingURI, PMOVN.RESTRICTION_P, restrictionURI);
333                 addStatementToSink(restrictionURI, RDF.TYPE, typeURI);
334                 addStatementToSink(restrictionURI, RDF.TYPE, getAtomicURI(selrestrs.get(0)));
335                 addStatementToSink(restrictionURI, PMO.VALUE_OBJ, voURI);
336                 if (pieces != null) {
337                     pieces.add(String.format("%s%s%s%s", sep1,
338                             selrestrs.get(0).getAttribute("Value"),
339                             selrestrs.get(0).getAttribute("type"), sep2));
340                 }
341             }
342             if (selrestrs.size() > 1) {
343 
344                 final URI logicURI = getLogicURI(selrestrse);
345 
346                 addStatementToSink(startingURI, PMOVN.RESTRICTION_P, restrictionURI);
347                 addStatementToSink(restrictionURI, RDF.TYPE, logicURI);
348                 addStatementToSink(restrictionURI, RDF.TYPE, typeURI);
349 
350                 int i = 0;
351                 for (final Element selrestr : selrestrs) {
352                     i++;
353                     final URI thisRestrictionURI = uriForRestriction(startingURI, suffix, i);
354 
355                     final URI voURI = PMOVN.lookup(lookup, selrestr.getAttribute("type"));
356                     if (voURI == null) {
357                         LOGGER.error("Value not found: {}:{}", lookup,
358                                 selrestr.getAttribute("type"));
359                     }
360                     addStatementToSink(restrictionURI, PMO.ITEM, thisRestrictionURI);
361                     addStatementToSink(thisRestrictionURI, RDF.TYPE, typeURI);
362                     addStatementToSink(thisRestrictionURI, RDF.TYPE, getAtomicURI(selrestr));
363                     addStatementToSink(thisRestrictionURI, PMO.VALUE_OBJ, voURI);
364                     if (pieces != null) {
365                         pieces.add(String.format("%s%s%s%s", sep1, selrestr.getAttribute("Value"),
366                                 selrestr.getAttribute("type"), sep2));
367                     }
368                 }
369             }
370 
371         }
372     }
373 
374     private void addFrameToSink(final String classID, final URI frameURI,
375             final Element frameElement) {
376 
377         final URI classURI = uriForRoleset(classID);
378         addStatementToSink(classURI, PMOVN.FRAME, frameURI);
379         addStatementToSink(classURI, PMOVN.DEFINES_FRAME, frameURI);
380 
381         addStatementToSink(frameURI, RDF.TYPE, PMOVN.VERBNET_FRAME);
382 
383         final Match description = JOOX.$(frameElement.getElementsByTagName("DESCRIPTION"));
384         addStatementToSink(frameURI, PMOVN.FRAME_DESC_NUMBER,
385                 description.attr("descriptionNumber"));
386         addStatementToSink(frameURI, PMOVN.FRAME_PRIMARY, description.attr("primary"));
387         addStatementToSink(frameURI, PMOVN.FRAME_SECONDARY, description.attr("secondary"));
388         addStatementToSink(frameURI, PMOVN.FRAME_XTAG, description.attr("xtag"));
389 
390         final Map<URI, URI> exampleURIs = new HashMap<>();
391 
392         final Match examples = JOOX.$(frameElement.getElementsByTagName("EXAMPLE"));
393         if (examples.size() == 1) {
394             final URI exampleURI = getExampleURI(frameURI);
395             final URI uri = addExampleToSink(frameURI, exampleURI, examples.get(0));
396             exampleURIs.put(exampleURI, uri);
397         }
398         if (examples.size() > 1) {
399             int i = 0;
400             for (final Element example : examples) {
401                 i++;
402 
403                 final URI exampleURI = getExampleURI(frameURI, i);
404                 final URI uri = addExampleToSink(frameURI, exampleURI, example);
405                 exampleURIs.put(exampleURI, uri);
406             }
407         }
408 
409         final Match syntax = JOOX.$(frameElement.getElementsByTagName("SYNTAX"));
410         if (syntax.size() == 1) {
411             final Element syntaxElement = syntax.get(0);
412             final SyntaxArrayLogic syntaxArrayLogic = new SyntaxArrayLogic(syntaxElement,
413                     frameURI, classID);
414             syntaxArrayLogic.add();
415 
416             for (final URI exampleURI : exampleURIs.keySet()) {
417                 final URI annotationSetURI = exampleURIs.get(exampleURI);
418 
419                 addStatementToSink(frameURI, PMOVN.FRAME_EXAMPLE, exampleURI, this.EXAMPLE_GRAPH);
420                 
421                 final URI predURI = createURI(annotationSetURI.toString() + "-pred");
422                 addStatementToSink(predURI, RDF.TYPE, NIF.ANNOTATION_C, this.EXAMPLE_GRAPH);
423                 addStatementToSink(annotationSetURI, PMO.ITEM, predURI, this.EXAMPLE_GRAPH);
424                 addStatementToSink(exampleURI, NIF.ANNOTATION_P, predURI, this.EXAMPLE_GRAPH);
425                 addStatementToSink(predURI, PMO.VALUE_OBJ, classURI, this.EXAMPLE_GRAPH);
426 
427                 for (final String role : syntaxArrayLogic.getRoles()) {
428                     final String rolePart = formatArg(role);
429                     final URI roleURI = createURI(annotationSetURI.toString() + "-" + rolePart);
430                     final URI argumentURI = uriForArgument(classID, role);
431 
432                     addStatementToSink(roleURI, RDF.TYPE, NIF.ANNOTATION_C, this.EXAMPLE_GRAPH);
433                     addStatementToSink(annotationSetURI, PMO.ITEM, roleURI, this.EXAMPLE_GRAPH);
434                     addStatementToSink(exampleURI, NIF.ANNOTATION_P, roleURI, this.EXAMPLE_GRAPH);
435                     addStatementToSink(roleURI, PMO.VALUE_OBJ, argumentURI, this.EXAMPLE_GRAPH);
436                 }
437 
438             }
439 
440             String pieces = String.join(" ", syntaxArrayLogic.getPieces());
441             pieces = pieces.trim();
442             if (pieces.length() > 0) {
443                 addStatementToSink(frameURI, PMOVN.FRAME_SYNTAX_DESCRIPTION, pieces, false);
444             }
445         } else {
446             LOGGER.warn("Syntax size is not 1");
447         }
448 
449         final Match semantics = JOOX.$(frameElement.getElementsByTagName("SEMANTICS"));
450         if (semantics.size() == 1) {
451             final Element semanticsElement = semantics.get(0);
452             final SemanticsArrayLogic semanticsArrayLogic = new SemanticsArrayLogic(
453                     semanticsElement, frameURI, classID);
454             semanticsArrayLogic.add();
455 
456             String pieces = String.join(" ", semanticsArrayLogic.getPieces());
457             pieces = pieces.trim();
458             if (pieces.length() > 0) {
459                 addStatementToSink(frameURI, PMOVN.FRAME_SEMANTICS_DESCRIPTION, pieces, false);
460             }
461         }
462     }
463 
464     class ArgumentArrayLogic extends ArrayLogicClass {
465 
466         protected String rolesetID;
467 
468         List<String> pieces = new ArrayList<>();
469 
470         public List<String> getPieces() {
471             return this.pieces;
472         }
473 
474         public void resetPieces() {
475             this.pieces = new ArrayList<>();
476         }
477 
478         public ArgumentArrayLogic(final Element startElement, final URI parentURI,
479                 final String rolesetID) {
480             super(startElement, parentURI);
481             this.rolesetID = rolesetID;
482         }
483 
484         @Override void addToSink(final Element element, final URI thisURI) {
485             addStatementToSink(thisURI, RDF.TYPE, PMOVN.PRED_ARG);
486             final String type = element.getAttribute("type");
487             String value = element.getAttribute("value");
488             this.pieces.add(value);
489 
490             boolean questionMark = false;
491 
492             if (value.startsWith("?")) {
493                 addStatementToSink(thisURI, PMOVN.IMPL_PRED_ARG,true);
494                 value = value.substring(1);
495                 questionMark = true;
496             } else addStatementToSink(thisURI, PMOVN.IMPL_PRED_ARG,false);
497 
498             addStatementToSink(thisURI, PMO.VALUE_DT, value);
499 
500             switch (type) {
501             case "Event":
502                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.EVENT_PRED_ARG);
503                 final String okValue = value.replaceAll("\\(.*\\)", "");
504                 final URI argType = PMOVN.lookup(PMOVN.EVENT_PRED_ARG_TYPE, okValue);
505                 if (argType != null) {
506                     addStatementToSink(thisURI, PMO.VALUE_OBJ, argType);
507                 }
508                 break;
509             case "Constant":
510                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.CONSTANT_PRED_ARG);
511                 break;
512             case "ThemRole":
513                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.THEM_ROLE_PRED_ARG);
514 
515                 // todo: maybe use a Set, just to avoid duplicates?
516                 final String[] parts = value.split("\\+|,");
517                 for (String part : parts) {
518                     part = part.replaceAll("_[ij]$", "");
519                     part = part.trim();
520                     //                    System.out.println(value + "---" + part);
521                     //                    URI argumentURI = uriForArgument(rolesetID, part);
522                     final URI thematicRoleURI = PMOVN.lookup(PMOVN.THEMATIC_ROLE_C, part);
523                     //                    System.out.println(thematicRoleURI);
524                     addStatementToSink(thisURI, PMO.VALUE_OBJ, thematicRoleURI);
525                 }
526                 break;
527             case "VerbSpecific":
528                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.VERB_SPECIFIC_PRED_ARG);
529                 break;
530             }
531         }
532 
533         @Override String getSuffix() {
534             return DEFAULT_ARG_SUFFIX;
535         }
536     }
537 
538     class SemanticsArrayLogic extends ArrayLogicClass {
539 
540         protected String rolesetID;
541         List<String> pieces = new ArrayList<>();
542 
543         public List<String> getPieces() {
544             return this.pieces;
545         }
546 
547         public void resetPieces() {
548             this.pieces = new ArrayList<>();
549         }
550 
551         public SemanticsArrayLogic(final Element startElement, final URI parentURI,
552                 final String rolesetID) {
553             super(startElement, parentURI);
554             this.rolesetID = rolesetID;
555         }
556 
557         @Override String getSuffix() {
558             return DEFAULT_PRED_SUFFIX;
559         }
560 
561         @Override void addToSink(final Element element, final URI thisURI) {
562             final String value = element.getAttribute("value");
563             final URI obj = PMOVN.createURI(value + "_pred");
564 
565             addStatementToSink(obj, RDF.TYPE, PMOVN.PRED_TYPE);
566             addStatementToSink(obj, RDFS.LABEL, value);
567 
568 
569 
570             URI thisA = PMOVN.PRED;
571             final String bool = element.getAttribute("bool");
572             if (bool != null && bool.equals("!")) {
573                 addStatementToSink(thisURI, PMOVN.NEG_PRE, true);
574             } else {
575                 addStatementToSink(thisURI, PMOVN.NEG_PRE, false);
576             }
577             addStatementToSink(thisURI, RDF.TYPE, thisA);
578             addStatementToSink(thisURI, PMO.VALUE_OBJ, obj);
579 
580             final Match args = JOOX.$(element.getElementsByTagName("ARGS"));
581             String argString = "";
582             if (args.size() == 1) {
583                 final Element argElement = args.get(0);
584                 final ArgumentArrayLogic argumentArrayLogic = new ArgumentArrayLogic(argElement,
585                         thisURI, this.rolesetID);
586                 argumentArrayLogic.add();
587 
588                 argString = String.join(", ", argumentArrayLogic.getPieces());
589             } else {
590                 LOGGER.warn("Args size is not 1");
591             }
592 
593             String semString = String.format("%s(%s)", value, argString.trim());
594             if (bool != null && bool.equals("!")) {
595                 semString = String.format("not(%s)", semString);
596             }
597             this.pieces.add(semString);
598         }
599     }
600 
601     class SyntaxArrayLogic extends ArrayLogicClass {
602 
603         protected String rolesetID;
604         List<String> pieces = new ArrayList<>();
605         List<String> roles = new ArrayList<>();
606 
607         public List<String> getPieces() {
608             return this.pieces;
609         }
610 
611         public void resetPieces() {
612             this.pieces = new ArrayList<>();
613         }
614 
615         public SyntaxArrayLogic(final Element startElement, final URI parentURI,
616                 final String rolesetID) {
617             super(startElement, parentURI);
618             this.rolesetID = rolesetID;
619         }
620 
621         public List<String> getRoles() {
622             return this.roles;
623         }
624 
625         @Override String getSuffix() {
626             return DEFAULT_SYNITEM_SUFFIX;
627         }
628 
629         @Override void addToSink(final Element element, final URI thisURI) {
630             final String tagName = element.getTagName();
631 
632             final String value = element.getAttribute("value");
633 
634             //            URI tmpURI = factory.createURI("http://premon.fbk.eu/resource/vn32-amalgamate-22.2-1_frame_1_SynItem_4");
635             //            System.out.println(thisURI);
636             //            if (thisURI.equals(tmpURI)) {
637             //                System.out.println("Yes!");
638             //                System.out.println(tagName);
639             //                System.out.println(value);
640             //            }
641 
642             switch (tagName) {
643             case "NP":
644                 this.pieces.add(value);
645                 this.roles.add(value);
646                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.NP_SYN_ITEM);
647                 final URI argumentURI = uriForArgument(this.rolesetID, value);
648                 addStatementToSink(thisURI, PMO.VALUE_OBJ, argumentURI);
649                 addRestrictions("SYNRESTRS", "SYNRESTR", thisURI, element, "synRes",
650                         PMOVN.SYNTACTIC_RESTRICTION, PMOVN.SYNTACTIC_RESTRICTION_PROPERTY,
651                         this.pieces, "[", "]");
652                 addRestrictions("SELRESTRS", "SELRESTR", thisURI, element, "selRes",
653                         PMOVN.ROLE_SELECTIONAL_RESTRICTION, PMOVN.ROLE_RESTRICTION_PROPERTY,
654                         this.pieces, "{{", "}}");
655                 break;
656             case "VERB":
657                 this.pieces.add("V");
658                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.VERB_SYN_ITEM);
659                 break;
660             case "PREP":
661                 if (value != null && value.length() > 0) {
662                     this.pieces.add(String.format("{%s}", value));
663                     final String[] values = value.split("\\s+");
664                     for (final String thisValue : values) {
665                         final URI lexicalEntryURI = addLexicalEntry(thisValue, thisValue, null,
666                                 null, "prep", getLexicon());
667                         addStatementToSink(thisURI, PMO.VALUE_OBJ, lexicalEntryURI);
668                     }
669                 }
670                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.PREP_SYN_ITEM);
671                 addRestrictions("SELRESTRS", "SELRESTR", thisURI, element, "selRes",
672                         PMOVN.PREPOSITION_SELECTIONAL_RESTRICTION,
673                         PMOVN.PREPOSITION_RESTRICTION_PROPERTY, this.pieces, "{{", "}}");
674                 break;
675             case "LEX":
676                 this.pieces.add(String.format("(%s)", value));
677                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.LEX_SYN_ITEM);
678                 addStatementToSink(thisURI, PMO.VALUE_DT, value);
679                 break;
680             case "ADV":
681                 this.pieces.add("ADV");
682                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.ADV_SYN_ITEM);
683                 break;
684             case "ADJ":
685                 this.pieces.add("ADJ");
686                 addStatementToSink(thisURI, RDF.TYPE, PMOVN.ADJ_SYN_ITEM);
687                 break;
688             }
689         }
690     }
691 
692     abstract class ArrayLogicClass {
693 
694         protected Element startElement;
695         protected URI parentURI;
696 
697         public ArrayLogicClass(final Element startElement, final URI parentURI) {
698             this.startElement = startElement;
699             this.parentURI = parentURI;
700         }
701 
702         public void add() {
703             final NodeList childNodes = this.startElement.getChildNodes();
704             int count = 0;
705             final List<URI> list = new ArrayList<>();
706 
707             for (int i = 0; i < childNodes.getLength(); i++) {
708                 final Node node = childNodes.item(i);
709                 if (node.getNodeType() == Node.ELEMENT_NODE) {
710                     final Element element = (Element) node;
711                     count++;
712 
713                     final URI thisSysURI = getThisURI(count);
714                     list.add(thisSysURI);
715                     addToSink(element, thisSysURI);
716                 }
717             }
718 
719             boolean isFirst = true;
720             URI prev = null;
721             for (final URI uri : list) {
722                 if (isFirst) {
723                     addStatementToSink(this.parentURI, PMO.FIRST, uri);
724                     isFirst = false;
725                 }
726 
727                 if (prev != null) {
728                     addStatementToSink(prev, PMO.NEXT, uri);
729                 }
730 
731                 prev = uri;
732             }
733         }
734 
735         URI getThisURI(final Integer index) {
736             final StringBuilder builder = new StringBuilder();
737             builder.append(this.parentURI.toString());
738             builder.append("_");
739             builder.append(getSuffix());
740             if (index != null) {
741                 builder.append("_").append(index);
742             }
743             return createURI(builder.toString());
744         }
745 
746         abstract void addToSink(Element element, URI thisURI);
747 
748         abstract String getSuffix();
749     }
750 
751     private URI addExampleToSink(final URI frameURI, final URI exampleURI, final Element example) {
752 
753         final URI annotationSetURI = uriForAnnotationSet(exampleURI, null);
754 
755         addStatementToSink(annotationSetURI, RDF.TYPE, PMO.ANNOTATION_SET, this.EXAMPLE_GRAPH);
756 
757 //        addStatementToSink(frameURI, PMO.EXAMPLE_P, exampleURI, this.EXAMPLE_GRAPH);
758         addStatementToSink(exampleURI, RDF.TYPE, PMO.EXAMPLE, this.EXAMPLE_GRAPH);
759         addStatementToSink(exampleURI, NIF.IS_STRING, example.getTextContent(), this.EXAMPLE_GRAPH);
760 
761         return annotationSetURI;
762     }
763 
764     private URI getExampleURI(final URI frameURI) {
765         return getExampleURI(frameURI, null);
766     }
767 
768     private URI getExampleURI(final URI frameURI, @Nullable final Integer index) {
769         final StringBuilder builder = new StringBuilder();
770         builder.append(frameURI.toString());
771         builder.append("_");
772         builder.append(DEFAULT_EXAMPLE_SUFFIX);
773         if (index != null) {
774             builder.append("_").append(index);
775         }
776         return createURI(builder.toString());
777     }
778 
779     private URI getFrameURI(final String rolesetID) {
780         return getFrameURI(rolesetID, null);
781     }
782 
783     private URI getFrameURI(final String rolesetID, @Nullable final Integer index) {
784         final StringBuilder builder = new StringBuilder();
785         builder.append(NAMESPACE);
786         builder.append(rolesetPart(rolesetID));
787         builder.append("_");
788         builder.append(DEFAULT_FRAME_SUFFIX);
789         if (index != null) {
790             builder.append("_").append(index);
791         }
792         return createURI(builder.toString());
793     }
794 
795     private URI getLogicURI(final Element selrestrse) {
796         final String logic = selrestrse.getAttribute("logic");
797         if (logic != null && logic.equals("or")) {
798             return PMOVN.OR_COMPOUND_RESTRICTION;
799         }
800 
801         return PMOVN.AND_COMPOUND_RESTRICTION;
802     }
803 
804     private URI getAtomicURI(final Element element) {
805         final String value = element.getAttribute("Value");
806         if (value.equals("+")) {
807             return PMOVN.EXIST_ATOMIC_RESTRICTION;
808         }
809         if (value.equals("-")) {
810             return PMOVN.ABSENT_ATOMIC_RESTRICTION;
811         }
812 
813         return null;
814     }
815 
816     @Override
817     public String getArgLabel() {
818         return "";
819     }
820 
821     protected URI getExternalLink(final String id) {
822         return createURI(String.format(LINK_PATTERN, id));
823     }
824 
825     protected URI uriForRestriction(final URI start, @Nullable final String suffix) {
826         return uriForRestriction(start, suffix, null);
827     }
828 
829     protected URI uriForRestriction(final URI start, @Nullable final String suffix,
830             @Nullable final Integer index) {
831         final StringBuilder builder = new StringBuilder();
832         builder.append(start.toString());
833         builder.append("_");
834         builder.append(suffix != null ? suffix : DEFAULT_RESTRICTION_SUFFIX);
835         if (index != null) {
836             builder.append("_").append(index);
837         }
838         return createURI(builder.toString());
839     }
840 
841     @Override
842     protected String formatArg(final String arg) {
843         return super.formatArg(arg).toLowerCase();
844     }
845 
846     @Override
847     protected URI getPosURI(final String textualPOS) {
848         switch (textualPOS) {
849         case "prep":
850             return LEXINFO.PREPOSITION;
851         }
852 
853         return LEXINFO.VERB;
854     }
855 }