1 package eu.fbk.dkm.pikes.resources.mpqa;
2
3 import com.google.common.base.Joiner;
4 import com.google.common.collect.Lists;
5 import com.google.common.collect.Maps;
6 import com.google.common.collect.Ordering;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 import javax.annotation.Nullable;
11 import java.util.Arrays;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Objects;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
17
18
19
20
21 public final class Record {
22
23 private final String line;
24
25 private final Span span;
26
27 private final String name;
28
29 private final String value;
30
31 private final Map<String, String> valueMap;
32
33 private static Pattern attribPatt = Pattern.compile("^\\s*[a-zA-Z0-9_-]+=");
34 private static Pattern endPatt = Pattern.compile("^\\s*$");
35 private static final Logger LOGGER = LoggerFactory.getLogger(Record.class);
36
37 public Record(final String line) {
38
39 final String[] tokens = line.trim().split("\t");
40
41 this.line = line;
42 this.span = new Span(tokens[1]);
43 this.name = tokens[3].trim();
44 this.value = tokens.length < 5 ? "" : Joiner.on(" ").join(
45 Arrays.asList(tokens).subList(4, tokens.length));
46 this.valueMap = Maps.newHashMap();
47
48 final List<String> entries = Lists.newArrayList();
49 int start = -1;
50 boolean insideQuote = false;
51 for (int i = 0; i < this.value.length(); ++i) {
52 final char c = this.value.charAt(i);
53 if (insideQuote) {
54 if (c == '\"') {
55 final String fromNow = this.value.substring(i + 1);
56 final Matcher attribMatcher = attribPatt.matcher(fromNow);
57 final Matcher endMatcher = endPatt.matcher(fromNow);
58 if (attribMatcher.find() || endMatcher.find()) {
59 insideQuote = false;
60 }
61 }
62 } else {
63 if (c == '\"') {
64 insideQuote = true;
65 } else if (start >= 0 && Character.isWhitespace(c)) {
66 entries.add(this.value.substring(start, i));
67 start = -1;
68 } else if (start < 0) {
69 start = i;
70 }
71 }
72 }
73 if (start >= 0) {
74 entries.add(this.value.substring(start));
75 }
76
77 for (final String entry : entries) {
78 final int index = entry.indexOf("=");
79 if (index >= 0) {
80 final String key = entry.substring(0, index).trim();
81 String value = entry.substring(index + 1).trim();
82 if (value.startsWith("\"") && value.endsWith("\"")) {
83 value = value.substring(1, value.length() - 1);
84 }
85 this.valueMap.put(key, value);
86 }
87 }
88 }
89
90 public Span getSpan() {
91 return this.span;
92 }
93
94 public String getName() {
95 return this.name;
96 }
97
98 public String getValue() {
99 return this.value;
100 }
101
102 public Map<String, String> getValueMap() {
103 return this.valueMap;
104 }
105
106 @Nullable
107 public String getValue(final String key) {
108 return this.valueMap.get(key);
109 }
110
111
112
113
114
115
116 @Override
117 public boolean equals(final Object object) {
118 if (object == this) {
119 return true;
120 }
121 if (!(object instanceof Record)) {
122 return false;
123 }
124 final Record other = (Record) object;
125 return this.span.equals(other.span) && this.name.equals(other.name);
126 }
127
128 @Override
129 public int hashCode() {
130 return Objects.hash(this.span, this.name);
131 }
132
133 @Override
134 public String toString() {
135 return this.line;
136 }
137
138 public static Ordering<Record> comparator(final String attribute) {
139 return new Ordering<Record>() {
140
141 @Override
142 public int compare(final Record left, final Record right) {
143 final String leftValue = left.getValue(attribute);
144 final String rightValue = right.getValue(attribute);
145 int result = Ordering.natural().nullsLast().compare(leftValue, rightValue);
146 if (result == 0) {
147 result = left.getSpan().compareTo(right.getSpan());
148 if (result == 0) {
149 result = left.getName().compareTo(right.getName());
150 }
151 }
152 return result;
153 }
154
155 };
156 }
157
158 }