org.aksw.jenax.graphql.sparql.Context Maven / Gradle / Ivy
The newest version!
package org.aksw.jenax.graphql.sparql;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.aksw.commons.path.core.Path;
import org.aksw.commons.path.core.PathStr;
import org.aksw.jenax.arq.util.prefix.PrefixMap2;
import org.aksw.jenax.facete.treequery2.api.NodeQuery;
import org.apache.jena.riot.system.PrefixMap;
import org.apache.jena.riot.system.PrefixMapFactory;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.graph.PrefixMappingAdapter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.graph.Traverser;
import graphql.language.Field;
// TODO Try to isolate prefix machinery
//class PrefixCxt {
// protected String base = null;
// protected PrefixMap prefixMap = null;
// protected String iri = null;
// protected String ns = null;
//
// public String getBase() {
// return base;
// }
// public void setBase(String base) {
// this.base = base;
// }
// public PrefixMap getPrefixMap() {
// return prefixMap;
// }
// public void setPrefixMap(PrefixMap prefixMap) {
// this.prefixMap = prefixMap;
// }
// public String getIri() {
// return iri;
// }
// public void setIri(String iri) {
// this.iri = iri;
// }
// public String getNs() {
// return ns;
// }
// public void setNs(String ns) {
// this.ns = ns;
// }
//
//
//}
/** Context for a GraphQL field. */
// XXX Replace field with selection or node because of fragments?
public class Context {
// Effective local values
protected Field field;
protected Context parent;
protected String base = null;
/** A stack of prefix maps is built from nesting using the PrefixMap2 class */
protected PrefixMap localPrefixMap = null;
protected String iri;
protected String ns;
// Computed effective values taking parent context into account
protected PrefixMap finalPrefixMap = null;
protected String finalBase = null;
protected String finalNs = null;
protected String finalIri = null;
// protected FacetPath facetPath = null;
protected NodeQuery nodeQuery;
// Contexts of immediate children. Used to reference information of fields by name
protected Map childContexts = new LinkedHashMap<>();
protected Cardinality thisCardinality;
protected Cardinality inheritedCardinality;
public Context(Context parent, Field field) {
super();
this.parent = parent;
this.field = field;
if (parent != null) {
this.inheritedCardinality = parent.getInheritedCardinality();
this.thisCardinality = parent.getInheritedCardinality();
} else {
this.inheritedCardinality = Cardinality.MANY;
this.thisCardinality = Cardinality.MANY;
}
}
public Path getPath() {
Path parentPath = parent != null ? parent.getPath() : PathStr.newAbsolutePath();
Path result = field == null
? parentPath
: parentPath.resolve(field.getName());
return result;
}
// public FacetPath getFacetPath() {
// return facetPath;
// }
//
// public void setFacetPath(FacetPath facetPath) {
// this.facetPath = facetPath;
// }
public NodeQuery getNodeQuery() {
return nodeQuery;
}
public void setNodeQuery(NodeQuery nodeQuery) {
this.nodeQuery = nodeQuery;
}
public Field getField() {
return field;
}
public Context newChildContext(Field field) {
String fieldName = field.getName();
Context result = new Context(this, field);
childContexts.put(fieldName, result);
return result;
}
public Context getParent() {
return parent;
}
public Map getChildContexts() {
return childContexts;
}
public Optional tryGetParent() {
return Optional.ofNullable(parent);
}
public void setBase(String iri) {
this.base = iri;
}
public String getBase() {
String result = base != null ? base : (parent != null ? parent.getBase() : null);
return result;
}
// public String getPrefix(String prefix) {
// String result = localPrefixMap != null ? localPrefixMap.get(prefix) : (parent != null ? parent.getPrefix(prefix) : null);
// return result;
// }
public PrefixMap getLocalPrefixMap() {
return localPrefixMap;
}
public void setLocalPrefixMap(PrefixMap prefixMap) {
this.localPrefixMap = prefixMap;
update();
}
public String getIri() {
return iri;
}
public void setIri(String iri) {
this.iri = iri;
}
public String getNs() {
return ns;
}
public void setNs(String ns) {
this.ns = ns;
}
public static T combine(T a, T b, BinaryOperator combiner, Supplier nullCase) {
T result = a == null
? b == null
? nullCase.get()
: b
: b == null
? a
: combiner.apply(a, b);
return result;
}
public void update() {
updatePrefixes();
}
public void updatePrefixes() {
finalPrefixMap = buildFinalPrefixMap();
PrefixMapping pm = new PrefixMappingAdapter(finalPrefixMap);
finalBase = base == null ? null : Optional.ofNullable(pm.getNsPrefixURI(base)).orElseGet(() -> pm.expandPrefix(base));
finalNs = ns == null ? null : Optional.ofNullable(pm.getNsPrefixURI(ns)).orElseGet(() -> pm.expandPrefix(ns));
finalIri = iri == null ? null : Optional.ofNullable(pm.getNsPrefixURI(iri)).orElseGet(() -> pm.expandPrefix(iri));
}
public PrefixMap buildFinalPrefixMap() {
PrefixMap parentMap = parent == null ? null : parent.getFinalPrefixMap();
PrefixMap result = combine(parentMap, localPrefixMap, PrefixMap2::new, PrefixMapFactory::emptyPrefixMap);
return result;
}
public PrefixMap getFinalPrefixMap() {
return finalPrefixMap;
}
public String getFinalBase() {
return finalBase != null ? finalBase : tryGetParent().map(Context::getFinalBase).orElse(null);
}
public String getFinalNs() {
return finalNs != null ? finalNs : tryGetParent().map(Context::getFinalNs).orElse(null);
}
public String getFinalIri() {
return finalIri != null ? finalIri : tryGetParent().map(Context::getFinalIri).orElse(null);
}
public Context findOnlyField(String fieldName) {
Set matches = findField(fieldName);
List> matchingPaths = matches.stream().map(Context::getPath).collect(Collectors.toList());
Context match;
if (matches.isEmpty()) {
throw new NoSuchElementException("Could not resolve field name " + fieldName + " at path " + this.getPath());
} else if (matches.size() > 1) {
throw new IllegalArgumentException("Ambiguous resolution. Field name + " + fieldName + " expected to resolve to 1 field. Got " + matchingPaths.size() + " fields: " + matchingPaths);
} else {
match = Iterables.getOnlyElement(matches);
}
return match;
}
public Set findField(String name) {
Set result = Streams.stream(Traverser.forTree(cxt -> cxt.getChildContexts().values()).depthFirstPreOrder(this))
.filter(cxt -> {
Field field = cxt.getField();
Set names = getEffectiveFieldNames(field);
boolean r = names.contains(name);
return r;
})
.collect(Collectors.toSet());
return result;
}
public static Set getEffectiveFieldNames(Field field) {
Set result = getAliases(field);
if (result.isEmpty()) {
result = Set.of(field.getName());
}
return result;
}
// Field has a getAlias() method - can we exploit that for our purpose???
// No, alias causes output fields to become renamed - we want to introduce a flat name by which a nested field can be referenced
public static Set getAliases(Field field) {
// String alias = field.getAlias();
// Set result = alias == null ? Set.of() : Set.of(alias);
Set result = field.getDirectives("as").stream()
.map(d -> GraphQlUtils.getArgValueAsString(d, "name", null)) // TODO Raise exception when field aliases are variables!
.collect(Collectors.toSet());
return result;
}
public Cardinality getThisCardinality() {
return thisCardinality;
}
public void setThisCardinality(Cardinality thisCardinality) {
this.thisCardinality = thisCardinality;
}
public Cardinality getInheritedCardinality() {
return inheritedCardinality;
}
public void setInheritedCardinality(Cardinality inheritedCardinality) {
this.inheritedCardinality = inheritedCardinality;
}
/** Whether the cardinality of the field is effectively single */
// public Cardinality getFinalCardinality() {
// Cardinality card = getCardinality();
// if (card == null && parent != null) {
// card = parent.getFinalCardinality();
// if (!card.isAll()) {
// card = null;
// }
// }
//
// if (card == null) {
// card = new Cardinality(false, false);
// }
// return card;
// }
// public static Set> findField(TreeDataMap, Field> tree, Path basePath, String name) {
// Set> result = Streams.stream(Traverser.>forTree(tree::getChildren).depthFirstPreOrder(basePath))
// .filter(path -> {
// Field field = tree.get(path);
// Set names = getEffectiveFieldNames(field);
// boolean r = names.contains(name);
// return r;
// })
// .collect(Collectors.toSet());
// return result;
// }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy