All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jena.sparql.util.Context Maven / Gradle / Ivy

There is a newer version: 5.2.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.sparql.util ;

import java.util.* ;
import java.util.concurrent.ConcurrentHashMap ;

import org.apache.jena.atlas.lib.Callback ;
import org.apache.jena.atlas.lib.Lib ;
import org.apache.jena.query.ARQ ;
import org.apache.jena.sparql.ARQConstants ;
import org.apache.jena.sparql.ARQException ;
import org.apache.jena.sparql.core.DatasetGraph ;

/**
 * A class for setting and keeping named values. Used to pass
 * implementation-specific parameters across general interfaces.
 */

public class Context {
    public static final Context      emptyContext = new Context(true) ;

    protected Map    context      = new ConcurrentHashMap<>() ;
    protected List> callbacks    = new ArrayList<>() ;
    protected boolean                readonly     = false ;

    /** Create an empty context */
    public Context() {}

    /* Create an empty context, mark it's readonly state */
    private Context(boolean readonly) {
        this.readonly = readonly ;
    }

    /**
     * Create a context and initialize it with a copy of the named values of
     * another one. Shallow copy: the values themselves are not copied
     */
    public Context(Context cxt) {
        putAll(cxt) ;
    }

    /**
     * Return a copy of this context. Modifications of the copy do not affect
     * the original context.
     */
    public Context copy() {
        return new Context(this) ;
    }

    // -- basic operations
    
    /** Get the object value of a property or null */
    @SuppressWarnings("unchecked")
    public  T get(Symbol property) {
        return (T) context.get(property) ;
    }

    /**
     * Get the object value of a property - return the default value if not
     * present .
     */
    public Object get(Symbol property, Object defaultValue) {
        Object x = context.get(property) ;
        if ( x == null )
            return defaultValue ;
        return x ;
    }

    /** Store a named value - overwrites any previous set value */
    public void put(Symbol property, Object value) {
        _put(property, value) ;
        doCallbacks(property) ;
    }

    /** Store a named value - overwrites any previous set value */
    public void set(Symbol property, Object value) {
        _put(property, value) ;
        doCallbacks(property) ;
    }

    private void _put(Symbol property, Object value) {
        if ( readonly )
            throw new ARQException("Context is readonly") ;
        if ( property == null )
            throw new ARQException("Context key is null") ;
        if ( value == null ) {
            context.remove(property) ;
            return ;
        }
        context.put(property, value) ;
    }

    /** Store a named value - overwrites any previous set value */
    public void set(Symbol property, boolean value) {
        if ( value )
            setTrue(property) ;
        else
            setFalse(property) ;
    }

    /** Store a named value only if it is not currently set */
    public void setIfUndef(Symbol property, Object value) {
        Object x = context.get(property) ;
        if ( x == null )
            put(property, value) ;
    }

    /** Remove any value associated with a property */
    public void remove(Symbol property) {
        context.remove(property) ;
        doCallbacks(property) ;
    }

    /** Remove any value associated with a property - alternative method name */
    public void unset(Symbol property) {
        context.remove(property) ;
        doCallbacks(property) ;
    }

    // ---- Helpers

    // -- Existence

    /** Is a property set? */
    public boolean isDefined(Symbol property) {
        return context.containsKey(property) ;
    }

    /** Is a property not set? */
    public boolean isUndef(Symbol property) {
        return !isDefined(property) ;
    }

    // -- as string

    /**
     * Get the value a string (uses .toString() if the value is not null) -
     * supply a default string value
     */
    public String getAsString(Symbol property, String defaultValue) {
        String x = getAsString(property) ;
        if ( x == null )
            return defaultValue ;
        return x ;
    }

    /** Get the value a string (uses .toString() if the value is not null) */
    public String getAsString(Symbol property) {
        Object x = context.get(property) ;
        if ( x == null )
            return null ;
        return x.toString() ;
    }
    
    /** Get the value as a a long value. The context entry can be a string, Integer or Long. */
    public int getInt(Symbol symbol, int defaultValue) {
        if (  isUndef(symbol) )
            return defaultValue ; 
        Object obj = context.get(symbol) ;
        if ( obj instanceof String ) {
            return Integer.parseInt((String)obj) ;
        } else if ( obj instanceof Integer ) {
            return ((Integer)obj).intValue() ;
        } else {
            throw new ARQException("Value for "+symbol+" is not a recoginized class: "+Lib.className(obj)) ;
        }
    }

    /** Get the value as a a long value. The context entry can be a string, Integer or Long. */
    public long getLong(Symbol symbol, long defaultValue) {
        if (  isUndef(symbol) )
            return defaultValue ; 
        Object obj = context.get(symbol) ;
        if ( obj instanceof String ) {
            return Long.parseLong((String)obj) ;
        } else if ( obj instanceof Integer ) {
            return ((Integer)obj).intValue() ;
        } else if ( obj instanceof Long ) {
            return ((Long)obj) ;
        } else {
            throw new ARQException("Value for "+symbol+" is not a recoginized class: "+Lib.className(obj)) ;
        }
    }
    
    public void putAll(Context other) {
        if ( readonly )
            throw new ARQException("Context is readonly") ;
        if ( other != null ) {
            for ( Map.Entry e : other.context.entrySet() )
                put(e.getKey(), e.getValue()) ;
        }
    }

    // -- true/false

    /** Set propety value to be true */
    public void setTrue(Symbol property) {
        set(property, Boolean.TRUE) ;
    }

    /** Set propety value to be false */
    public void setFalse(Symbol property) {
        set(property, Boolean.FALSE) ;
    }

    /** Is the value 'true' (either set to the string "true" or Boolean.TRUE) */
    public boolean isTrue(Symbol property) {
        return isTrue(property, false) ;
    }

    /**
     * Is the value 'true' (either set to the string "true" or Boolean.TRUE) or
     * undefined?
     */
    public boolean isTrueOrUndef(Symbol property) {
        return isTrue(property, true) ;
    }

    private boolean isTrue(Symbol property, boolean dft) {
        Object x = get(property) ;
        if ( x == null )
            return dft ;
        if ( x instanceof String ) {
            String s = (String)x ;
            if ( s.equalsIgnoreCase("true") )
                return true ;
        }
        return x.equals(Boolean.TRUE) ;
    }

    /** Is the value 'false' (either set to the string "false" or Boolean.FALSE) */
    public boolean isFalse(Symbol property) {
        return isFalse(property, false) ;
    }

    /**
     * Is the value 'false' (either set to the string "false" or Boolean.FALSE)
     * or undefined
     */
    public boolean isFalseOrUndef(Symbol property) {
        return isFalse(property, true) ;
    }

    private boolean isFalse(Symbol property, boolean dft) {
        Object x = get(property) ;
        if ( x == null )
            return dft ;
        if ( x instanceof String ) {
            String s = (String)x ;
            if ( s.equalsIgnoreCase("false") )
                return true ;
        }
        return x.equals(Boolean.FALSE) ;
    }

    // -- Test for value

    /** Test whether a named value is a specific value (.equals) */

    public boolean hasValue(Symbol property, Object value) {
        Object x = get(property) ;
        if ( x == null && value == null )
            return true ;
        if ( x == null || value == null )
            return false ;
        return x.equals(value) ;
    }

    /** Test whether a named value (as a string) has a specific string form */

    public boolean hasValueAsString(Symbol property, String value) {
        return hasValueAsString(property, value, false) ;
    }

    /**
     * Test whether a named value (as a string) has a specific string form - can
     * ignore case
     */
    public boolean hasValueAsString(Symbol property, String value, boolean ignoreCase) {
        String s = getAsString(property) ;
        if ( s == null && value == null )
            return true ;
        if ( s == null || value == null )
            return false ;

        if ( ignoreCase )
            return s.equalsIgnoreCase(value) ;
        return s.equals(value) ;
    }

    /** Set of properties (as Symbols) currently defined */
    public Set keys() {
        return context.keySet() ;
    }

    /** Return the number of context items */
    public int size() {
        return context.size() ;
    }

    // ---- Callbacks
    public synchronized void addCallback(Callback m) {
        callbacks.add(m) ;
    }

    public synchronized void removeCallback(Callback m) {
        callbacks.remove(m) ;
    }

    public synchronized List> getCallbacks() {
        return Collections.unmodifiableList(callbacks) ;
    }

    private synchronized void doCallbacks(Symbol symbol) {
        for ( Callback c : callbacks ) {
            c.apply(symbol) ;
        }
    }

    @Override
    public String toString() {
        String x = "" ;
        String sep = "" ;
        for ( Symbol s : keys() ) {
            Object value = get(s) ;
            x = x + sep + s + " = " + value ;
            sep = "\n" ;
        }
        return x ;
    }

    // Put any per-dataset execution global configuration state here.
    public static Context setupContext(Context context, DatasetGraph dataset) {
        if ( context == null )
            context = ARQ.getContext() ; // Already copied?
        context = context.copy() ;

        if ( dataset != null && dataset.getContext() != null )
            // Copy per-dataset settings.
            context.putAll(dataset.getContext()) ;

        context.set(ARQConstants.sysCurrentTime, NodeFactoryExtra.nowAsDateTime()) ;

        // Allocators.
        // context.set(ARQConstants.sysVarAllocNamed, new
        // VarAlloc(ARQConstants.allocVarMarkerExec)) ;
        // context.set(ARQConstants.sysVarAllocAnon, new
        // VarAlloc(ARQConstants.allocVarAnonMarkerExec)) ;
        // Add VarAlloc for variables and bNodes (this is not the parse name).
        // More added later e.g. query (if there is a query), algebra form (in
        // setOp)

        return context ;
    }

    @Override
    public int hashCode() {
        final int prime = 31 ;
        int result = 1 ;
        result = prime * result + ((context == null) ? 0 : context.hashCode()) ;
        result = prime * result + (readonly ? 1231 : 1237) ;
        return result ;
    }

    @Override
    public boolean equals(Object obj) {
        if ( this == obj )
            return true ;
        if ( obj == null )
            return false ;
        if ( getClass() != obj.getClass() )
            return false ;
        Context other = (Context)obj ;
        if ( context == null ) {
            if ( other.context != null )
                return false ;
        } else if ( !context.equals(other.context) )
            return false ;
        if ( readonly != other.readonly )
            return false ;
        return true ;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy