/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.bigdata.rdf.sparql.ast.eval; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.openrdf.model.Literal; import org.openrdf.model.URI; import org.openrdf.model.Value; import com.bigdata.bop.IVariable; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.sparql.ast.GraphPatternGroup; import com.bigdata.rdf.sparql.ast.IGroupMemberNode; import com.bigdata.rdf.sparql.ast.StatementPatternNode; import com.bigdata.rdf.sparql.ast.TermNode; import com.bigdata.rdf.sparql.ast.service.ServiceCallCreateParams; import com.bigdata.rdf.sparql.ast.service.ServiceNode; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.BD; /** * Helper class for parsing an extracting SERVICE parameters. The SERVICE group * graph pattern should consist of zero or triples whose Subject is * {@link BD#SERVICE_PARAM}. There may be zero or more such triple patterns. The * Predicate (key) and Object (val) positions for those triple patterns are * extracted into a {@link ServiceParams} object. For each key, there may be one * or more values. * * <pre> * SERVICE <uri> { * bd:serviceParam :key1 :val1 . * bd:serviceParam :key1 :val2 . * bd:serviceParam :key2 :val3 . * } * </pre> */ public class ServiceParams { private static final Logger log = Logger .getLogger(AbstractServiceFactory.class); /** * The map of service params. */ private final Map<URI, List<TermNode>> params; public ServiceParams() { this.params = new LinkedHashMap<URI, List<TermNode>>(); } /** * Add. */ public void add(final URI param, final TermNode value) { if (!params.containsKey(param)) { params.put(param, new LinkedList<TermNode>()); } params.get(param).add(value); } /** * Set (clear and add). */ public void set(final URI param, final TermNode value) { clear(param); add(param, value); } /** * Clear. */ public void clear(final URI param) { params.remove(param); } /** * Check for existence. */ public boolean contains(final URI param) { return params.containsKey(param); } /** * Get a singleton value for the specified param. */ public TermNode get(final URI param, final TermNode defaultValue) { if (params.containsKey(param)) { final List<TermNode> values = params.get(param); if (values.size() > 1) { throw new RuntimeException("not a singleton param"); } return values.get(0); } return defaultValue; } /** * Helper. */ public Boolean getAsBoolean(final URI param) { return getAsBoolean(param, null); } /** * Helper. */ public Boolean getAsBoolean(final URI param, final Boolean defaultValue) { final Literal term = getAsLiteral(param, null); if (term != null) { return term.booleanValue(); } return defaultValue; } /** * Helper. */ public Integer getAsInt(final URI param) { return getAsInt(param, null); } /** * Helper. */ public Integer getAsInt(final URI param, final Integer defaultValue) { final Literal term = getAsLiteral(param, null); if (term != null) { return term.intValue(); } return defaultValue; } /** * Helper. */ public Long getAsLong(final URI param) { return getAsLong(param, null); } /** * Helper. */ public Long getAsLong(final URI param, final Long defaultValue) { final Literal term = getAsLiteral(param, null); if (term != null) { return term.longValue(); } return defaultValue; } /** * Helper. */ public String getAsString(final URI param) { return getAsString(param, null); } /** * Helper. */ public String getAsString(final URI param, final String defaultValue) { final Literal term = getAsLiteral(param, null); if (term != null) { return term.stringValue(); } return defaultValue; } /** * Helper. */ public Literal getAsLiteral(final URI param) { return getAsLiteral(param, null); } /** * Helper. */ public Literal getAsLiteral(final URI param, final Literal defaultValue) { final TermNode term = get(param, null); if (term != null) { if (term.isVariable()) { throw new IllegalArgumentException("not a constant"); } final Value v = term.getValue(); if (!(v instanceof Literal)) { throw new IllegalArgumentException("not a literal"); } return ((Literal) v); } return defaultValue; } /** * Helper. */ public URI getAsURI(final URI param) { return getAsURI(param, null); } /** * Helper. */ public URI getAsURI(final URI param, final URI defaultValue) { final TermNode term = get(param, null); if (term != null) { if (term.isVariable()) { throw new IllegalArgumentException("not a constant"); } final Value v = term.getValue(); if (!(v instanceof URI)) { throw new IllegalArgumentException("not a uri"); } return ((URI) v); } return defaultValue; } /** * Helper. */ @SuppressWarnings("rawtypes") public IVariable<IV> getAsVar(final URI param) { return getAsVar(param, null); } /** * Helper. */ @SuppressWarnings("rawtypes") public IVariable<IV> getAsVar(final URI param, final IVariable<IV> defaultValue) { final TermNode term = get(param, null); if (term != null) { if (!term.isVariable()) { throw new IllegalArgumentException("not a var"); } return (IVariable<IV>) term.getValueExpression(); } return defaultValue; } /** * Helper. */ public List<TermNode> get(final URI param) { if (params.containsKey(param)) { return params.get(param); } return Collections.emptyList(); } /** * Iterator. */ public Iterator<Map.Entry<URI, List<TermNode>>> iterator() { return params.entrySet().iterator(); } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("["); for (Map.Entry<URI, List<TermNode>> e : params.entrySet()) { final URI param = e.getKey(); final List<TermNode> terms = e.getValue(); sb.append(param).append(": "); if (terms.size() == 1) { sb.append(terms.get(0)); } else { sb.append("["); for (TermNode t : terms) { sb.append(t).append(", "); } sb.setLength(sb.length() - 2); sb.append("]"); } sb.append(", "); } if (sb.length() > 1) sb.setLength(sb.length() - 2); sb.append("]"); return sb.toString(); } /** * Gather the service params (any statement patterns with the subject of * {@link BD#SERVICE_PARAM}. */ static public ServiceParams gatherServiceParams( final ServiceCallCreateParams createParams) { if (createParams == null) throw new IllegalArgumentException(); final AbstractTripleStore store = createParams.getTripleStore(); if (store == null) throw new IllegalArgumentException(); final ServiceNode serviceNode = createParams.getServiceNode(); if (serviceNode == null) throw new IllegalArgumentException(); final GraphPatternGroup<IGroupMemberNode> group = serviceNode .getGraphPattern(); if (group == null) throw new IllegalArgumentException(); final ServiceParams serviceParams = new ServiceParams(); final Iterator<IGroupMemberNode> it = group.iterator(); while (it.hasNext()) { final IGroupMemberNode node = it.next(); if (node instanceof StatementPatternNode) { final StatementPatternNode sp = (StatementPatternNode) node; final TermNode s = sp.s(); if (s.isConstant() && BD.SERVICE_PARAM.equals(s.getValue())) { if (sp.p().isVariable()) { throw new RuntimeException( "not a valid service param triple pattern, " + "predicate must be constant: " + sp); } final URI param = (URI) sp.p().getValue(); serviceParams.add(param, sp.o()); } } } if (log.isDebugEnabled()) { log.debug(serviceParams); } return serviceParams; } } // class ServiceParams