<commit_before>/*
 * Copyright 2007 <NAME>
 *
 * 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 org.danann.cernunnos;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;

/**
 * Base class for simple container tasks.  <code>AbstractContainerTask</code> 
 * provides the <code>SUBTASKS</code> reagent for subclasses to add to their 
 * formulas.
 */
public abstract class AbstractContainerTask implements Task {
    protected final Log log = LogFactory.getLog(this.getClass());

	private List<Task> subtasks;

	/*
	 * Public API.
	 */
	
	/**
	 * Use this <code>List</code> to create a <code>SUBTASKS</code> reagent that 
	 * will not cause <code>POSSIBLE PROGRAMMING ERROR...</code> warnings when 
	 * empty.  
	 */
	public static final List<Element> SUPPRESS_EMPTY_SUBTASKS_WARNINGS = 
	                        createSuppressEmptySubtasksWarningsList();
	
	/**
	 * Subclasses <strong>must</strong> invoke <code>super.init</code> within 
	 * their own <code>init</code> method for subtasks to bootstrap properly.
	 * 
	 * @param config Task configuration information provided by the Cernunnos 
	 * runtime.
	 */
	public void init(EntityConfig config) {
	    this.subtasks = this.loadSubtasks(config, SUBTASKS, true);
	}
	
	/*
	 * Protected API.
	 */
	
	/**
	 * Initializes (but does not bootstrap) the collection of child tasks.  
	 */
	protected AbstractContainerTask() {
		// Instance Members.
		this.subtasks = null;
	}

	/**
	 * Subclasses <strong>must</strong> add a reagent named "SUBTASKS" to their 
	 * formulas in order that child tasks get bootstrapped properly.  They can 
	 * use this one except in cases where a different XPath expression must be 
	 * specified.
	 */
	protected static final Reagent SUBTASKS = new SimpleReagent("SUBTASKS", "*", ReagentType.NODE_LIST, List.class, 
								"The set of tasks that are children of this task.", new LinkedList<Task>());
	
	/**
	 * Abstracts the loading of subtasks for a Reagent into a single menthod
	 * 
	 * @param warnIfMissing If true a WARN level log message will be issued if no tasks are loaded for the Reagent 
	 */
	@SuppressWarnings("unchecked")
    protected List<Task> loadSubtasks(EntityConfig config, Reagent subtasksPhrase, boolean warnIfMissing) {
	    final List<Task> subtasks = new LinkedList<Task>();
	    
	    final List<Element> taskElements = (List<Element>) config.getValue(subtasksPhrase);
	    final Grammar grammar = config.getGrammar();
        for (final Element taskElement : taskElements) {
            final Task task = grammar.newTask(taskElement, this);
            subtasks.add(task);
        }
        
        // There's likely an error in the Cernunnos XML 
        // if we don't have any subtasks, issue a warning...
        if (warnIfMissing && subtasks.size() == 0 && log.isWarnEnabled()) {
            log.warn("POSSIBLE PROGRAMMING ERROR:  Class '" 
                    + getClass().getName() 
                    + "' has an empty collection of " + subtasksPhrase.getName());
        }
        
        return subtasks;
	}
<commit_msg>Issue 87: Add source and name of element being processed so the empty subtasks error message. Including the source file would be good too but I didn't see how to do that.<commit_after>/*
 * Copyright 2007 <NAME>
 *
 * 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 org.danann.cernunnos;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;

/**
 * Base class for simple container tasks.  <code>AbstractContainerTask</code> 
 * provides the <code>SUBTASKS</code> reagent for subclasses to add to their 
 * formulas.
 */
public abstract class AbstractContainerTask implements Task {
    protected final Log log = LogFactory.getLog(this.getClass());

	private List<Task> subtasks;

	/*
	 * Public API.
	 */
	
	/**
	 * Use this <code>List</code> to create a <code>SUBTASKS</code> reagent that 
	 * will not cause <code>POSSIBLE PROGRAMMING ERROR...</code> warnings when 
	 * empty.  
	 */
	public static final List<Element> SUPPRESS_EMPTY_SUBTASKS_WARNINGS = 
	                        createSuppressEmptySubtasksWarningsList();
	
	/**
	 * Subclasses <strong>must</strong> invoke <code>super.init</code> within 
	 * their own <code>init</code> method for subtasks to bootstrap properly.
	 * 
	 * @param config Task configuration information provided by the Cernunnos 
	 * runtime.
	 */
	public void init(EntityConfig config) {
	    this.subtasks = this.loadSubtasks(config, SUBTASKS, true);
	}
	
	/*
	 * Protected API.
	 */
	
	/**
	 * Initializes (but does not bootstrap) the collection of child tasks.  
	 */
	protected AbstractContainerTask() {
		// Instance Members.
		this.subtasks = null;
	}

	/**
	 * Subclasses <strong>must</strong> add a reagent named "SUBTASKS" to their 
	 * formulas in order that child tasks get bootstrapped properly.  They can 
	 * use this one except in cases where a different XPath expression must be 
	 * specified.
	 */
	protected static final Reagent SUBTASKS = new SimpleReagent("SUBTASKS", "*", ReagentType.NODE_LIST, List.class, 
								"The set of tasks that are children of this task.", new LinkedList<Task>());
	
	/**
	 * Abstracts the loading of subtasks for a Reagent into a single menthod
	 * 
	 * @param warnIfMissing If true a WARN level log message will be issued if no tasks are loaded for the Reagent 
	 */
	@SuppressWarnings("unchecked")
    protected List<Task> loadSubtasks(EntityConfig config, Reagent subtasksPhrase, boolean warnIfMissing) {
	    final List<Task> subtasks = new LinkedList<Task>();
	    
	    final List<Element> taskElements = (List<Element>) config.getValue(subtasksPhrase);
	    final Grammar grammar = config.getGrammar();
        for (final Element taskElement : taskElements) {
            final Task task = grammar.newTask(taskElement, this);
            subtasks.add(task);
        }
        
        // There's likely an error in the Cernunnos XML 
        // if we don't have any subtasks, issue a warning...
        if (warnIfMissing && subtasks.size() == 0 && log.isWarnEnabled()) {
            log.warn("POSSIBLE PROGRAMMING ERROR:  Class '" 
                    + getClass().getName() 
                    + "' has an empty collection of " + subtasksPhrase.getName()            
                    + "\n\t\tSource:  " + config.getSource()
                    + "\n\t\tEntity Name:  " + config.getEntryName());
        }
        
        return subtasks;
	}

{'fraction_non_alphanumeric': 0.09653752091646287, 'fraction_numerical': 0.0030892006693268117, 'mean_word_length': 3.0873224618621777, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 57, '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': '3023072', 'n_tokens_mistral': 2294, 'n_tokens_neox': 2109, 'n_words': 760}