1   /*
2    * RDFpro - An extensible tool for building stream-oriented RDF processing libraries.
3    * 
4    * Written in 2015 by Francesco Corcoglioniti with support by Alessio Palmero Aprosio and Marco
5    * Rospocher. Contact info on http://rdfpro.fbk.eu/
6    * 
7    * To the extent possible under law, the authors have dedicated all copyright and related and
8    * neighboring rights to this software to the public domain worldwide. This software is
9    * distributed without any warranty.
10   * 
11   * You should have received a copy of the CC0 Public Domain Dedication along with this software.
12   * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13   */
14  package eu.fbk.rdfpro.util;
15  
16  import java.util.Comparator;
17  import java.util.List;
18  import java.util.Objects;
19  import java.util.function.Function;
20  
21  import com.google.common.collect.Lists;
22  
23  import org.openrdf.model.Resource;
24  import org.openrdf.model.Statement;
25  import org.openrdf.model.URI;
26  import org.openrdf.model.Value;
27  import org.openrdf.model.ValueFactory;
28  
29  public enum StatementComponent implements Function<Statement, Value>, Comparator<Statement> {
30  
31      SUBJECT('s', (byte) 0) {
32  
33          @Override
34          public Resource apply(final Statement statement) {
35              return statement.getSubject();
36          }
37  
38          @Override
39          public Statement replace(final Statement statement, final Value value,
40                  final ValueFactory factory) {
41              if (Objects.equals(statement.getSubject(), value)) {
42                  return statement;
43              } else if (statement.getContext() == null) {
44                  return factory.createStatement((Resource) value, statement.getPredicate(),
45                          statement.getObject());
46              } else {
47                  return factory.createStatement((Resource) value, statement.getPredicate(),
48                          statement.getObject(), statement.getContext());
49              }
50          }
51  
52      },
53  
54      PREDICATE('p', (byte) 1) {
55  
56          @Override
57          public URI apply(final Statement statement) {
58              return statement.getPredicate();
59          }
60  
61          @Override
62          public Statement replace(final Statement statement, final Value value,
63                  final ValueFactory factory) {
64              if (Objects.equals(statement.getPredicate(), value)) {
65                  return statement;
66              } else if (statement.getContext() == null) {
67                  return factory.createStatement(statement.getSubject(), (URI) value,
68                          statement.getObject());
69              } else {
70                  return factory.createStatement(statement.getSubject(), (URI) value,
71                          statement.getObject(), statement.getContext());
72              }
73          }
74  
75      },
76  
77      OBJECT('o', (byte) 2) {
78  
79          @Override
80          public Value apply(final Statement statement) {
81              return statement.getObject();
82          }
83  
84          @Override
85          public Statement replace(final Statement statement, final Value value,
86                  final ValueFactory factory) {
87              if (Objects.equals(statement.getContext(), value)) {
88                  return statement;
89              } else if (value == null) {
90                  return factory.createStatement(statement.getSubject(), statement.getPredicate(),
91                          statement.getObject());
92              } else {
93                  return factory.createStatement(statement.getSubject(), statement.getPredicate(),
94                          statement.getObject(), (Resource) value);
95              }
96          }
97  
98      },
99  
100     CONTEXT('c', (byte) 3) {
101 
102         @Override
103         public Resource apply(final Statement statement) {
104             return statement.getContext();
105         }
106 
107         @Override
108         public Statement replace(final Statement statement, final Value value,
109                 final ValueFactory factory) {
110             if (Objects.equals(statement.getObject(), value)) {
111                 return statement;
112             } else if (statement.getContext() == null) {
113                 return factory.createStatement(statement.getSubject(), statement.getPredicate(),
114                         value);
115             } else {
116                 return factory.createStatement(statement.getSubject(), statement.getPredicate(),
117                         value, statement.getContext());
118             }
119         }
120 
121     };
122 
123     private char letter;
124 
125     private byte index;
126 
127     private StatementComponent(final char letter, final byte index) {
128         this.letter = letter;
129         this.index = index;
130     }
131 
132     public final char getLetter() {
133         return this.letter;
134     }
135 
136     public byte getIndex() {
137         return this.index;
138     }
139 
140     @Override
141     public abstract Value apply(final Statement statement);
142 
143     @Override
144     public final int compare(final Statement first, final Statement second) {
145         if (first == null && second == null) {
146             return 0;
147         } else if (first != null && second == null) {
148             return 1;
149         } else if (first == null && second != null) {
150             return -1;
151         } else {
152             return Statements.valueComparator().compare(apply(first), apply(second));
153         }
154     }
155 
156     public final Statement replace(final Statement statement, final Value value) {
157         return replace(statement, value, Statements.VALUE_FACTORY);
158     }
159 
160     public abstract Statement replace(Statement statement, final Value value, ValueFactory factory);
161 
162     public static StatementComponent forLetter(char letter) {
163         letter = Character.toLowerCase(letter);
164         for (final StatementComponent component : values()) {
165             if (component.getLetter() == letter) {
166                 return component;
167             }
168         }
169         throw new IllegalArgumentException("Unknown statement component '" + letter + "'");
170     }
171 
172     public static List<StatementComponent> forLetters(final CharSequence letters) {
173         return forLetters(letters, false);
174     }
175 
176     public static List<StatementComponent> forLetters(final CharSequence letters,
177             final boolean acceptDuplicates) {
178         final List<StatementComponent> result = Lists.newArrayList();
179         for (int i = 0; i < letters.length(); ++i) {
180             final StatementComponent component = forLetter(letters.charAt(i));
181             if (!acceptDuplicates && result.contains(component)) {
182                 throw new IllegalArgumentException("Duplicate statement component " + component);
183             }
184             result.add(component);
185         }
186         return result;
187     }
188 
189 }