<commit_before>/*
 * Copyright 2013-2019, Centre for Genomic Regulation (CRG)
 *
 * Licensed 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 nextflow.processor
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.atomic.AtomicBoolean

import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import groovy.transform.PackageScope
import groovy.util.logging.Slf4j
import groovyx.gpars.dataflow.DataflowReadChannel
import groovyx.gpars.dataflow.DataflowWriteChannel
import nextflow.Global
import nextflow.exception.ProcessException
import nextflow.util.KryoHelper
/**
 * Map used to delegate variable resolution to script scope
 *
 * @author <NAME> <<EMAIL>>
 */
@Slf4j
class TaskContext implements Map<String,Object>, Cloneable {

    @Delegate
    private Map<String,Object> holder

    /**
     * Used to show the override warning message only the very first time
     */
    private transient final overrideWarnShown = new AtomicBoolean()

    /**
     * The main script owning the process
     */
    private Script script

    /**
     * The process name
     */
    private String name

    /**
     * The name of the variables not hold in the task context, but referenced in the global script binding object
     */
    private transient Set<String> variableNames

    TaskContext( TaskProcessor processor, Map holder = [:]) {
        assert holder != null
        this.holder = holder
        this.script = processor.ownerScript
        this.name = processor.name

        // fetch all the variables names referenced by the script body and retain
        // only the ones not declared as input or output, because these are supposed to
        // to be the ones provided by the *external* script context
        variableNames = processor.getTaskBody().getValNames() ?: []
        if( variableNames ) {
            Set<String> declaredNames = []
            declaredNames.addAll( processor.config.getInputs().getNames() )
            declaredNames.addAll( processor.config.getOutputs().getNames()  )
            if( declaredNames )
                variableNames = variableNames - declaredNames
        }

        log.trace "Binding names for '$name' > $variableNames"
    }


    protected TaskContext(Script script, Map holder, String name) {
        this.script = script
        this.holder = holder
        this.name = name
        def names = script.getBinding()?.getVariables()?.keySet()
        this.variableNames = names ? new HashSet<>(names) : new HashSet<>()
        log.trace "Binding names for '$name' > $variableNames"
    }

    /** ONLY FOR TEST PURPOSE -- do not use */
    protected TaskContext() { }

    TaskContext clone() {
        def copy = (TaskContext)super.clone()
        copy.setHolder( (Map)holder.clone() )
        return copy
    }

    /**
     * @return The inner map holding the process variables
     */
    public Map<String,Object> getHolder() { holder }

    private void setHolder( Map<String,Object> holder ) {
        this.holder = holder
    }

    /**
     * @return The script instance to which this map reference i.e. the main script object
     */
    public Script getScript() { script }

    /**
     * @return
     *      The set of variable and properties referenced in the user script.
     *      NOTE: it includes properties in the form {@code object.propertyName}
     */
    public Set<String> getVariableNames() { variableNames }

    @Override
    String toString() {
        "DelegateMap[process: $name; script: ${script?.class?.name}; holder: ${holder}]"
    }

    @Override
    public Object get(Object property) {
        assert property

        if( holder.containsKey(property) ) {
            return holder.get(property)
        }

        if( script?.getBinding()?.hasVariable(property.toString()) ) {
            return script.getBinding().getVariable(property.toString())
        }

        throw new MissingPropertyException("Unknown variable '$property' -- Make sure you didn't misspell it or define somewhere in the script before use it", property as String, null)
    }
<commit_msg>Minor grammar in task context error message<commit_after>/*
 * Copyright 2013-2019, Centre for Genomic Regulation (CRG)
 *
 * Licensed 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 nextflow.processor
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.atomic.AtomicBoolean

import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import groovy.transform.PackageScope
import groovy.util.logging.Slf4j
import groovyx.gpars.dataflow.DataflowReadChannel
import groovyx.gpars.dataflow.DataflowWriteChannel
import nextflow.Global
import nextflow.exception.ProcessException
import nextflow.util.KryoHelper
/**
 * Map used to delegate variable resolution to script scope
 *
 * @author <NAME> <<EMAIL>>
 */
@Slf4j
class TaskContext implements Map<String,Object>, Cloneable {

    @Delegate
    private Map<String,Object> holder

    /**
     * Used to show the override warning message only the very first time
     */
    private transient final overrideWarnShown = new AtomicBoolean()

    /**
     * The main script owning the process
     */
    private Script script

    /**
     * The process name
     */
    private String name

    /**
     * The name of the variables not hold in the task context, but referenced in the global script binding object
     */
    private transient Set<String> variableNames

    TaskContext( TaskProcessor processor, Map holder = [:]) {
        assert holder != null
        this.holder = holder
        this.script = processor.ownerScript
        this.name = processor.name

        // fetch all the variables names referenced by the script body and retain
        // only the ones not declared as input or output, because these are supposed to
        // to be the ones provided by the *external* script context
        variableNames = processor.getTaskBody().getValNames() ?: []
        if( variableNames ) {
            Set<String> declaredNames = []
            declaredNames.addAll( processor.config.getInputs().getNames() )
            declaredNames.addAll( processor.config.getOutputs().getNames()  )
            if( declaredNames )
                variableNames = variableNames - declaredNames
        }

        log.trace "Binding names for '$name' > $variableNames"
    }


    protected TaskContext(Script script, Map holder, String name) {
        this.script = script
        this.holder = holder
        this.name = name
        def names = script.getBinding()?.getVariables()?.keySet()
        this.variableNames = names ? new HashSet<>(names) : new HashSet<>()
        log.trace "Binding names for '$name' > $variableNames"
    }

    /** ONLY FOR TEST PURPOSE -- do not use */
    protected TaskContext() { }

    TaskContext clone() {
        def copy = (TaskContext)super.clone()
        copy.setHolder( (Map)holder.clone() )
        return copy
    }

    /**
     * @return The inner map holding the process variables
     */
    public Map<String,Object> getHolder() { holder }

    private void setHolder( Map<String,Object> holder ) {
        this.holder = holder
    }

    /**
     * @return The script instance to which this map reference i.e. the main script object
     */
    public Script getScript() { script }

    /**
     * @return
     *      The set of variable and properties referenced in the user script.
     *      NOTE: it includes properties in the form {@code object.propertyName}
     */
    public Set<String> getVariableNames() { variableNames }

    @Override
    String toString() {
        "DelegateMap[process: $name; script: ${script?.class?.name}; holder: ${holder}]"
    }

    @Override
    public Object get(Object property) {
        assert property

        if( holder.containsKey(property) ) {
            return holder.get(property)
        }

        if( script?.getBinding()?.hasVariable(property.toString()) ) {
            return script.getBinding().getVariable(property.toString())
        }

        throw new MissingPropertyException("Unknown variable '$property' -- Make sure it is not misspelt and defined somewhere in the script before using it", property as String, null)
    }

{'fraction_non_alphanumeric': 0.09133060168212206, 'fraction_numerical': 0.003019193444037093, 'mean_word_length': 2.7810843864655523, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7322232', 'n_tokens_mistral': 2445, 'n_tokens_neox': 2362, 'n_words': 840}