Skip to content

Commit

Permalink
Move filtering by preference to 3-arg getProperty
Browse files Browse the repository at this point in the history
This avoids some of the code duplication we had, as the
logic really should have been in the 3-argument getProperty
and not the 2-argument one (which is only for convenience
and for the _literal suffix).
  • Loading branch information
agarciadom committed Dec 20, 2024
1 parent 8c4f1d7 commit 6d18c51
Showing 1 changed file with 31 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@

public class RDFResource extends RDFModelElement {
protected static final String LITERAL_SUFFIX = "_literal";
enum LiteralMode {

public enum LiteralMode {
RAW, VALUES_ONLY
}

Expand All @@ -54,47 +54,28 @@ public Resource getResource() {

public Collection<Object> getProperty(String property, IEolContext context) {
final RDFQualifiedName pName = RDFQualifiedName.from(property, this.owningModel::getNamespaceURI);
Collection<Object> value = getProperty(pName, context, LiteralMode.VALUES_ONLY);

Collection<Object> value = getProperty(pName, context, LiteralMode.RAW);
if (pName.languageTag == null && !value.stream().anyMatch(p -> p instanceof RDFResource)) {
value = filterByPreferredLanguage(value, LiteralMode.RAW);
}
if (!value.isEmpty()) {
return convertLiteralsToValues(value);
}

if (pName.localName.endsWith(LITERAL_SUFFIX)) {
if (value.isEmpty() && pName.localName.endsWith(LITERAL_SUFFIX)) {
final String localNameWithoutSuffix = pName.localName.substring(0,
pName.localName.length() - LITERAL_SUFFIX.length());
RDFQualifiedName withoutLiteral = pName.withLocalName(localNameWithoutSuffix);

value = getProperty(withoutLiteral, context, LiteralMode.RAW);
if (pName.languageTag == null && !value.stream().anyMatch(p -> p instanceof RDFResource)) {
value = filterByPreferredLanguage(value, LiteralMode.RAW);
}
}

return value;
}

private Collection<Object> convertLiteralsToValues(Collection<Object> value) {
protected Collection<Object> convertLiteralsToValues(Collection<Object> value) {
return value.stream()
.map(e -> e instanceof RDFLiteral ? ((RDFLiteral)e).getValue() : e)
.collect(Collectors.toList());
}

private Collection<Object> filterByPreferredLanguage(Collection<Object> value, LiteralMode literalMode) {
protected Collection<Object> filterByPreferredLanguage(Collection<Object> value) {
// If no preferred languages are specified, don't do any filtering
if (super.getModel().getLanguagePreference().isEmpty()) {
switch (literalMode) {
case RAW:
return value;
case VALUES_ONLY:
return value.stream().map(e -> e instanceof RDFLiteral
? ((RDFLiteral) e).getValue() : e).collect(Collectors.toList());
default:
throw new IllegalArgumentException("Unknown literal mode " + literalMode);
}
return value;
}

// Otherwise, group literals by language tag
Expand All @@ -111,28 +92,14 @@ private Collection<Object> filterByPreferredLanguage(Collection<Object> value, L

for (String tag : super.getModel().getLanguagePreference()) {
if (literalsByTag.containsKey(tag)) {
switch (literalMode) {
case RAW:
return new ArrayList<>(literalsByTag.get(tag));
case VALUES_ONLY:
return literalsByTag.get(tag).stream().map(l ->
l.getValue()).collect(Collectors.toList());
}
return new ArrayList<>(literalsByTag.get(tag));
}
}

// If we don't find any matches in the preferred languages,
// fall back to the untagged literals (if any).
Collection<RDFLiteral> rawFromUntagged = literalsByTag.get("");
switch (literalMode) {
case RAW:
return new ArrayList<>(rawFromUntagged);
case VALUES_ONLY:
return rawFromUntagged.stream().map(l -> l.getValue())
.collect(Collectors.toList());
default:
throw new IllegalArgumentException("Unknown literal mode " + literalMode);
}
return new ArrayList<>(rawFromUntagged);
}

public Collection<Object> getProperty(RDFQualifiedName pName, IEolContext context, LiteralMode literalMode) {
Expand All @@ -158,13 +125,14 @@ public Collection<Object> getProperty(RDFQualifiedName pName, IEolContext contex
});
}

Collection<Object> rawValues;
if (pName.prefix == null) {
// If no prefix was specified, watch out for ambiguity and issue warning in that case
ListMultimap<String, Object> values = MultimapBuilder.hashKeys().arrayListValues().build();
while (itStatements.hasNext()) {
Statement stmt = itStatements.next();
values.put(stmt.getPredicate().getURI(),
convertToModelObject(stmt.getObject(), literalMode));
convertToModelObject(stmt.getObject()));
}

final Set<String> distinctKeys = values.keySet();
Expand All @@ -176,15 +144,30 @@ public Collection<Object> getProperty(RDFQualifiedName pName, IEolContext contex
));
}

return values.values();
rawValues = values.values();
} else {
// Prefix was specified: we don't have to worry about ambiguity
final List<Object> values = new ArrayList<>();
while (itStatements.hasNext()) {
Statement stmt = itStatements.next();
values.add(convertToModelObject(stmt.getObject(), literalMode));
values.add(convertToModelObject(stmt.getObject()));
}
return values;
rawValues = values;
}

// Filter by preferred languages if any are set
if (pName.languageTag == null && !rawValues.stream().anyMatch(p -> p instanceof RDFResource)) {
rawValues = filterByPreferredLanguage(rawValues);
}

// Convert literals to values depending on mode
switch (literalMode) {
case VALUES_ONLY:
return convertLiteralsToValues(rawValues);
case RAW:
return rawValues;
default:
throw new IllegalArgumentException("Unknown literal mode " + literalMode);
}
}

Expand All @@ -201,14 +184,9 @@ public String getUri() {
return resource.getURI();
}

protected Object convertToModelObject(RDFNode node, LiteralMode lMode) {
protected Object convertToModelObject(RDFNode node) {
if (node instanceof Literal) {
switch (lMode) {
case RAW:
return new RDFLiteral((Literal) node, this.owningModel);
case VALUES_ONLY:
return ((Literal) node).getValue();
}
return new RDFLiteral((Literal) node, this.owningModel);
} else if (node instanceof Resource) {
return new RDFResource((Resource) node, this.owningModel);
}
Expand Down

0 comments on commit 6d18c51

Please sign in to comment.