1   package eu.fbk.knowledgestore.server.http;
2   
3   import java.io.Serializable;
4   import java.util.List;
5   import java.util.Set;
6   
7   import javax.annotation.Nullable;
8   
9   import com.google.common.base.MoreObjects;
10  import com.google.common.base.Objects;
11  import com.google.common.base.Preconditions;
12  import com.google.common.base.Splitter;
13  import com.google.common.collect.ImmutableList;
14  import com.google.common.collect.ImmutableSet;
15  
16  import org.openrdf.model.URI;
17  import org.openrdf.model.impl.URIImpl;
18  import org.openrdf.model.vocabulary.DCTERMS;
19  import org.openrdf.model.vocabulary.RDF;
20  
21  import eu.fbk.knowledgestore.data.XPath;
22  import eu.fbk.knowledgestore.vocabulary.KS;
23  
24  public final class UIConfig implements Serializable {
25  
26      private static final long serialVersionUID = 1L;
27  
28      private static final int DEFAULT_RESULT_LIMIT = 100;
29  
30      private static final Set<URI> DEFAULT_RESOURCE_OVERVIEW_PROPERTIES = ImmutableSet.of(
31              DCTERMS.CREATED, DCTERMS.TITLE);
32  
33      private static final Set<URI> DEFAULT_MENTION_OVERVIEW_PROPERTIES = ImmutableSet.of( //
34              RDF.TYPE, KS.REFERS_TO);
35  
36      private static final URI DEFAULT_DENOTED_BY_PROPERTY = new URIImpl(
37              "http://groundedannotationframework.org/gaf#denotedBy");
38  
39      private static final boolean DEFAULT_DENOTED_BY_ALLOWS_GRAPHS = true;
40  
41      private static final boolean DEFAULT_REFERS_TO_FUNCTIONAL = true;
42  
43      private final int resultLimit;
44  
45      private final List<URI> resourceOverviewProperties;
46  
47      private final List<URI> mentionOverviewProperties;
48  
49      private final List<Category> mentionCategories;
50  
51      private final List<Example> lookupExamples;
52  
53      private final List<Example> sparqlExamples;
54  
55      private final URI denotedByProperty;
56  
57      private final boolean denotedByAllowsGraphs;
58  
59      private final boolean refersToFunctional;
60  
61      private UIConfig(final Builder builder) {
62          this.resultLimit = MoreObjects.firstNonNull(builder.resultLimit, DEFAULT_RESULT_LIMIT);
63          this.resourceOverviewProperties = ImmutableList.copyOf(MoreObjects.firstNonNull(
64                  builder.resourceOverviewProperties, DEFAULT_RESOURCE_OVERVIEW_PROPERTIES));
65          this.mentionOverviewProperties = ImmutableList.copyOf(MoreObjects.firstNonNull(
66                  builder.mentionOverviewProperties, DEFAULT_MENTION_OVERVIEW_PROPERTIES));
67          this.mentionCategories = builder.mentionCategories == null ? ImmutableList.<Category>of()
68                  : ImmutableList.copyOf(builder.mentionCategories);
69          this.lookupExamples = builder.lookupExamples == null ? ImmutableList.<Example>of()
70                  : ImmutableList.copyOf(builder.lookupExamples);
71          this.sparqlExamples = builder.sparqlExamples == null ? ImmutableList.<Example>of()
72                  : ImmutableList.copyOf(builder.sparqlExamples);
73          this.denotedByProperty = builder.denotedByProperty == null ? DEFAULT_DENOTED_BY_PROPERTY
74                  : builder.denotedByProperty;
75          this.denotedByAllowsGraphs = builder.denotedByAllowsGraphs == null ? DEFAULT_DENOTED_BY_ALLOWS_GRAPHS
76                  : builder.denotedByAllowsGraphs;
77          this.refersToFunctional = builder.refersToFunctional == null ? DEFAULT_REFERS_TO_FUNCTIONAL
78                  : builder.refersToFunctional;
79      }
80  
81      public static Builder builder() {
82          return new Builder();
83      }
84  
85      public int getResultLimit() {
86          return this.resultLimit;
87      }
88  
89      public List<URI> getResourceOverviewProperties() {
90          return this.resourceOverviewProperties;
91      }
92  
93      public List<URI> getMentionOverviewProperties() {
94          return this.mentionOverviewProperties;
95      }
96  
97      public List<Category> getMentionCategories() {
98          return this.mentionCategories;
99      }
100 
101     public List<Example> getLookupExamples() {
102         return this.lookupExamples;
103     }
104 
105     public List<Example> getSparqlExamples() {
106         return this.sparqlExamples;
107     }
108 
109     public URI getDenotedByProperty() {
110         return this.denotedByProperty;
111     }
112 
113     public boolean isDenotedByAllowsGraphs() {
114         return this.denotedByAllowsGraphs;
115     }
116 
117     public boolean isRefersToFunctional() {
118         return this.refersToFunctional;
119     }
120 
121     @Override
122     public boolean equals(final Object object) {
123         if (object == this) {
124             return true;
125         }
126         if (!(object instanceof UIConfig)) {
127             return false;
128         }
129         final UIConfig other = (UIConfig) object;
130         return this.resultLimit == other.resultLimit
131                 && this.resourceOverviewProperties.equals(other.resourceOverviewProperties)
132                 && this.mentionOverviewProperties.equals(other.mentionOverviewProperties)
133                 && this.mentionCategories.equals(other.mentionCategories)
134                 && this.lookupExamples.equals(other.lookupExamples)
135                 && this.sparqlExamples.equals(other.sparqlExamples);
136     }
137 
138     @Override
139     public int hashCode() {
140         return Objects.hashCode(this.resultLimit, this.resourceOverviewProperties,
141                 this.mentionOverviewProperties, this.mentionCategories, this.lookupExamples,
142                 this.sparqlExamples);
143     }
144 
145     @Override
146     public String toString() {
147         return MoreObjects.toStringHelper(this).add("resultLimit", this.resultLimit)
148                 .add("resourceOverviewProperties", this.resourceOverviewProperties)
149                 .add("mentionOverviewProperties", this.mentionOverviewProperties)
150                 .add("mentionCategories", this.mentionCategories)
151                 .add("lookupExamples", this.lookupExamples)
152                 .add("sparqlExamples", this.sparqlExamples).toString();
153     }
154 
155     public static final class Category implements Serializable {
156 
157         private static final long serialVersionUID = 1L;
158 
159         private final String label;
160 
161         private final String style;
162 
163         private final XPath condition;
164 
165         public Category(final String label, final String style, final XPath condition) {
166             this.label = Preconditions.checkNotNull(label);
167             this.style = Preconditions.checkNotNull(style);
168             this.condition = Preconditions.checkNotNull(condition);
169         }
170 
171         public String getLabel() {
172             return this.label;
173         }
174 
175         public String getStyle() {
176             return this.style;
177         }
178 
179         public XPath getCondition() {
180             return this.condition;
181         }
182 
183         @Override
184         public boolean equals(final Object object) {
185             if (object == this) {
186                 return true;
187             }
188             if (!(object instanceof Category)) {
189                 return false;
190             }
191             final Category other = (Category) object;
192             return this.label.equals(other.label) //
193                     && this.style.equals(other.style) //
194                     && this.condition.equals(other.condition);
195         }
196 
197         @Override
198         public int hashCode() {
199             return Objects.hashCode(this.label, this.style, this.condition);
200         }
201 
202         @Override
203         public String toString() {
204             return MoreObjects.toStringHelper(this) //
205                     .add("label", this.label) //
206                     .add("style", this.style) //
207                     .add("condition", this.condition) //
208                     .toString();
209         }
210 
211     }
212 
213     public static final class Example implements Serializable {
214 
215         private static final long serialVersionUID = 1L;
216 
217         private final String label;
218 
219         private final String value;
220 
221         public Example(final String label, final String value) {
222             this.label = Preconditions.checkNotNull(label);
223             this.value = normalizeMultilineString(Preconditions.checkNotNull(value));
224         }
225 
226         public String getLabel() {
227             return this.label;
228         }
229 
230         public String getValue() {
231             return this.value;
232         }
233 
234         @Override
235         public boolean equals(final Object object) {
236             if (object == this) {
237                 return true;
238             }
239             if (!(object instanceof Example)) {
240                 return false;
241             }
242             final Example other = (Example) object;
243             return this.label.equals(other.label) && this.value.equals(other.value);
244         }
245 
246         @Override
247         public int hashCode() {
248             return Objects.hashCode(this.label, this.value);
249         }
250 
251         @Override
252         public String toString() {
253             return MoreObjects.toStringHelper(this) //
254                     .add("label", this.label) //
255                     .add("value", this.value) //
256                     .toString();
257         }
258 
259         private static final String normalizeMultilineString(final String string) {
260 
261             final List<String> lines = ImmutableList.copyOf(Splitter.on('\n').split(string));
262 
263             int start = Integer.MAX_VALUE;
264             for (final String line : lines) {
265                 int index = 0;
266                 while (index < line.length() && Character.isSpaceChar(line.charAt(index))) {
267                     ++index;
268                 }
269                 if (index < line.length()) {
270                     start = Math.min(start, index);
271                 }
272             }
273 
274             String separator = "";
275             final StringBuilder builder = new StringBuilder();
276             for (final String line : lines) {
277                 if (!line.trim().isEmpty()) {
278                     builder.append(separator).append(
279                             line.substring(Math.min(line.length(), start)));
280                     separator = "\n";
281                 }
282             }
283 
284             return builder.toString();
285         }
286 
287     }
288 
289     public static final class Builder {
290 
291         @Nullable
292         private Integer resultLimit;
293 
294         @Nullable
295         private Iterable<? extends URI> resourceOverviewProperties;
296 
297         @Nullable
298         private Iterable<? extends URI> mentionOverviewProperties;
299 
300         @Nullable
301         private Iterable<? extends Category> mentionCategories;
302 
303         @Nullable
304         private Iterable<? extends Example> lookupExamples;
305 
306         @Nullable
307         private Iterable<? extends Example> sparqlExamples;
308 
309         @Nullable
310         private URI denotedByProperty;
311 
312         @Nullable
313         private Boolean denotedByAllowsGraphs;
314 
315         @Nullable
316         private Boolean refersToFunctional;
317 
318         public Builder resultLimit(@Nullable final Integer resultLimit) {
319             this.resultLimit = resultLimit;
320             return this;
321         }
322 
323         public Builder resourceOverviewProperties(
324                 @Nullable final Iterable<? extends URI> resourceOverviewProperties) {
325             this.resourceOverviewProperties = resourceOverviewProperties;
326             return this;
327         }
328 
329         public Builder mentionOverviewProperties(
330                 @Nullable final Iterable<? extends URI> mentionOverviewProperties) {
331             this.mentionOverviewProperties = mentionOverviewProperties;
332             return this;
333         }
334 
335         public Builder mentionCategories(
336                 @Nullable final Iterable<? extends Category> mentionCategories) {
337             this.mentionCategories = mentionCategories;
338             return this;
339         }
340 
341         public Builder lookupExamples(@Nullable final Iterable<? extends Example> lookupExamples) {
342             this.lookupExamples = lookupExamples;
343             return this;
344         }
345 
346         public Builder sparqlExamples(@Nullable final Iterable<? extends Example> sparqlExamples) {
347             this.sparqlExamples = sparqlExamples;
348             return this;
349         }
350 
351         public Builder denotedByProperty(@Nullable final URI denotedByProperty) {
352             this.denotedByProperty = denotedByProperty;
353             return this;
354         }
355 
356         public Builder denotedByAllowsGraphs(@Nullable final Boolean denotedByAllowsGraphs) {
357             this.denotedByAllowsGraphs = denotedByAllowsGraphs;
358             return this;
359         }
360 
361         public Builder refersToFunctional(@Nullable final Boolean refersToFunctional) {
362             this.refersToFunctional = refersToFunctional;
363             return this;
364         }
365 
366         public UIConfig build() {
367             return new UIConfig(this);
368         }
369 
370     }
371 
372 }