text:
package org.javarosa.core.model;

import org.commcare.cases.query.QueryContext;
import org.commcare.cases.query.ScopeLimitedReferenceRequestCache;
import org.commcare.modern.util.Pair;
import org.javarosa.core.log.WrappedException;
import org.javarosa.core.model.actions.Action;
import org.javarosa.core.model.actions.ActionController;
import org.javarosa.core.model.actions.FormSendCalloutHandler;
import org.javarosa.core.model.condition.Condition;
import org.javarosa.core.model.condition.Constraint;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.model.condition.IConditionExpr;
import org.javarosa.core.model.condition.IFunctionHandler;
import org.javarosa.core.model.condition.Recalculate;
import org.javarosa.core.model.condition.Triggerable;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.data.IntegerData;
import org.javarosa.core.model.data.InvalidData;
import org.javarosa.core.model.data.SelectMultiData;
import org.javarosa.core.model.data.SelectOneData;
import org.javarosa.core.model.data.helper.Selection;
import org.javarosa.core.model.instance.AbstractTreeElement;
import org.javarosa.core.model.instance.DataInstance;
import org.javarosa.core.model.instance.FormInstance;
import org.javarosa.core.model.instance.InstanceInitializationFactory;
import org.javarosa.core.model.instance.InvalidReferenceException;
import org.javarosa.core.model.instance.TreeElement;
import org.javarosa.core.model.instance.TreeReference;
import org.javarosa.core.model.trace.EvaluationTrace;
import org.javarosa.core.model.trace.ReducingTraceReporter;
import org.javarosa.core.model.util.restorable.RestoreUtils;
import org.javarosa.core.model.utils.InstrumentationUtils;
import org.javarosa.core.model.utils.ItemSetUtils;
import org.javarosa.core.services.locale.Localizer;
import org.javarosa.core.services.storage.IMetaData;
import org.javarosa.core.util.CacheTable;
import org.javarosa.core.util.DataUtil;
import org.javarosa.core.util.ShortestCycleAlgorithm;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapList;
import org.javarosa.core.util.externalizable.ExtWrapListPoly;
import org.javarosa.core.util.externalizable.ExtWrapMap;
import org.javarosa.core.util.externalizable.ExtWrapNullable;
import org.javarosa.core.util.externalizable.ExtWrapTagged;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import org.javarosa.model.xform.XPathReference;
import org.javarosa.xpath.XPathException;
import org.javarosa.xpath.XPathTypeMismatchException;
import org.javarosa.xpath.analysis.AnalysisInvalidException;
import org.javarosa.xpath.analysis.TreeReferenceAccumulatingAnalyzer;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Vector;

import javax.annotation.Nullable;

/**
 * Definition of a form. This has some meta data about the form definition and a
 * collection of groups together with question branching or skipping rules.
 *
 * @author Daniel Kayiwa, Drew Roos
 */
public class FormDef implements IFormElement, IMetaData,
        ActionController.ActionResultProcessor {
    public static final String STORAGE_KEY = "FORMDEF";
    private static final int TEMPLATING_RECURSION_LIMIT = 10;

    /**
     * Hierarchy of questions, groups and repeats in the form
     */
    private Vector<IFormElement> children;
    /**
     * A collection of group definitions.
     */
    private int id;
    /**
     * The numeric unique identifier of the form definition on the local device
     */
    private String title;
    /**
     * The display title of the form.
     */
    private String name;

    private Vector<XFormExtension> extensions;

    /**
     * A unique external name that is used to identify the form between machines
     */
    private Localizer localizer;

    // This list is topologically ordered, meaning for any tA
    // and tB in the list, where tA comes before tB, evaluating tA cannot
    // depend on any result from evaluating tB
    private ArrayList<Triggerable> triggerables;

    // <IConditionExpr> contents of <output> tags that serve as parameterized
    // arguments to captions
    private Vector outputFragments;

    /**
     * Map references to the calculate/relevancy conditions that depend on that
     * reference's value. Used to trigger re-evaluation of those conditionals
     * when the reference is updated.
     */
    private HashMap<TreeReference, Vector<Triggerable>> triggerIndex;

    /**
     * Associates repeatable nodes with the Condition that determines their
     * relevancy.
     */
    private HashMap<TreeReference, Condition> conditionRepeatTargetIndex;

    public EvaluationContext exprEvalContext;

    // XML ID's cannot start with numbers, so this should never conflict
    private static final String DEFAULT_SUBMISSION_PROFILE = "1";

    private Hashtable<String, SubmissionProfile> submissionProfiles;

    /**
     * Secondary and external instance pointers
     */
    private Hashtable<String, DataInstance> formInstances;

    private FormInstance mainInstance = null;

    private boolean mDebugModeEnabled = false;

    private final Vector<Triggerable> triggeredDuringInsert = new Vector<>();

    private ActionController actionController;
    //If this instance is just being edited, don't fire end of form events
    private boolean isCompletedInstance;

    private boolean mProfilingEnabled = false;
    private boolean useExpressionCaching;

    FormSendCalloutHandler sendCalloutHandler;

    /**
     * Cache children that trigger target will cascade to. For speeding up
     * calculations that determine what needs to be triggered when a value
     * changes.
     */
    private final CacheTable<TreeReference, ArrayList<TreeReference>> cachedCascadingChildren =
            new CacheTable<>();

    public FormDef() {
        this(false);
    }

    public FormDef(boolean useExpressionCaching) {
        setID(-1);
        setChildren(null);
        triggerables = new ArrayList<>();
        triggerIndex = new HashMap<>();
        //This is kind of a wreck...
        setEvaluationContext(new EvaluationContext(null));
        outputFragments = new Vector();
        submissionProfiles = new Hashtable<>();
        formInstances = new Hashtable<>();
        extensions = new Vector<>();
        actionController = new ActionController();
        this.useExpressionCaching = useExpressionCaching;
    }

    /**
     * Getters and setters for the vectors tha
     */
    public void addNonMainInstance(DataInstance instance) {
        formInstances.put(instance.getInstanceId(), instance);
        this.setEvaluationContext(new EvaluationContext(null));
    }

    /**
     * Get an instance based on a name
     */
    public DataInstance getNonMainInstance(String name) {
        if (!formInstances.containsKey(name)) {
            return null;
        }
        return formInstances.get(name);
    }

    public Enumeration getNonMainInstances() {
        return formInstances.elements();
    }

    /**
     * Set the main instance
     */
    public void setInstance(FormInstance fi) {
        mainInstance = fi;
        fi.setFormId(getID());
        this.setEvaluationContext(new EvaluationContext(null));
        attachControlsToInstanceData();
    }

    /**
     * Get the main instance
     */
    public FormInstance getMainInstance() {
        return mainInstance;
    }

    public FormInstance getInstance() {
        return getMainInstance();
    }

    // ---------- child elements
    @Override
    public void addChild(IFormElement fe) {
        this.children.addElement(fe);
    }

    @Override
    public IFormElement getChild(int i) {
        if (i < this.children.size())
            return this.children.elementAt(i);

        throw new ArrayIndexOutOfBoundsException(
                "FormDef: invalid child index: " + i + " only "
                        + children.size() + " children");
    }

    public IFormElement getChild(FormIndex index) {
        IFormElement element = this;
        while (index != null && index.isInForm()) {
            element = element.getChild(index.getLocalIndex());
            index = index.getNextLevel();
        }
        return element;
    }

    /**
     * Dereference the form index and return a Vector of all interstitial nodes
     * (top-level parent first; index target last)
     *
     * Ignore 'new-repeat' node for now; just return/stop at ref to
     * yet-to-be-created repeat node (similar to repeats that already exist)
     */
    public Vector explodeIndex(FormIndex index) {
        Vector<Integer> indexes = new Vector<>();
        Vector<Integer> multiplicities = new Vector<>();
        Vector<IFormElement> elements = new Vector<>();

        collapseIndex(index, indexes, multiplicities, elements);
        return elements;
    }

    // take a reference, find the instance node it refers to (factoring in
    // multiplicities)

    public TreeReference getChildInstanceRef(FormIndex index) {
        Vector<Integer> indexes = new Vector<>();
        Vector<Integer> multiplicities = new Vector<>();
        Vector<IFormElement> elements = new Vector<>();

        collapseIndex(index, indexes, multiplicities, elements);
        return getChildInstanceRef(elements, multiplicities);
    }

    /**
     * Return a tree reference which follows the path down the concrete elements provided
     * along with the multiplicities provided.
     */
    public TreeReference getChildInstanceRef(Vector<IFormElement> elements,
                                             Vector<Integer> multiplicities) {
        if (elements.size() == 0) {
            return null;
        }

        // get reference for target element
        TreeReference ref = FormInstance.unpackReference(elements.lastElement().getBind()).clone();
        for (int i = 0; i < ref.size(); i++) {
            //There has to be a better way to encapsulate this
            if (ref.getMultiplicity(i) != TreeReference.INDEX_ATTRIBUTE) {
                ref.setMultiplicity(i, 0);
            }
        }

        // fill in multiplicities for repeats along the way
        for (int i = 0; i < elements.size(); i++) {
            IFormElement temp = elements.elementAt(i);
            if (temp instanceof GroupDef && ((GroupDef)temp).isRepeat()) {
                TreeReference repRef = FormInstance.unpackReference(temp.getBind());
                if (repRef.isParentOf(ref, false)) {
                    int repMult = multiplicities.elementAt(i);
                    ref.setMultiplicity(repRef.size() - 1, repMult);
                } else {
                    // question/repeat hierarchy is not consistent with
                    // instance instance and bindings
                    return null;
                }
            }
        }

        return ref;
    }

    public void setLocalizer(Localizer l) {
        this.localizer = l;
    }

    // don't think this should ever be called(!)
    @Override
    public XPathReference getBind() {
        throw new RuntimeException("method not implemented");
    }

    public void setValue(IAnswerData data, TreeReference ref) {
        setValue(data, ref, mainInstance.resolveReference(ref));
    }

    public void setValue(IAnswerData data, TreeReference ref, TreeElement node) {
        setAnswer(data, node);
        triggerTriggerables(ref);
        //TODO: pre-populate fix-count repeats here?
    }

    public void setAnswer(IAnswerData data, TreeReference ref) {
        setAnswer(data, mainInstance.resolveReference(ref));
    }

    public void setAnswer(IAnswerData data, TreeElement node) {
        node.setAnswer(data);
    }

    /**
     * Deletes the inner-most repeat that this node belongs to and returns the
     * corresponding FormIndex. Behavior is currently undefined if you call this
     * method on a node that is not contained within a repeat.
     */
    public FormIndex deleteRepeat(FormIndex index) {
        Vector<Integer> indexes = new Vector<>();
        Vector<Integer> multiplicities = new Vector<>();
        Vector<IFormElement> elements = new Vector<>();
        collapseIndex(index, indexes, multiplicities, elements);

        // loop backwards through the elements, removing objects from each
        // vector, until we find a repeat
        // TODO: should probably check to make sure size > 0
        for (int i = elements.size() - 1; i >= 0; i--) {
            IFormElement e = elements.elementAt(i);
            if (e instanceof GroupDef && ((GroupDef)e).isRepeat()) {
                break;
            } else {
                indexes.removeElementAt(i);
                multiplicities.removeElementAt(i);
                elements.removeElementAt(i);
            }
        }

        // build new formIndex which includes everything
        // up to the node we're going to remove
        FormIndex newIndex = buildIndex(indexes, multiplicities, elements);

        TreeReference deleteRef = getChildInstanceRef(newIndex);
        TreeElement deleteElement = mainInstance.resolveReference(deleteRef);
        TreeReference parentRef = deleteRef.getParentRef();
        TreeElement parentElement = mainInstance.resolveReference(parentRef);

        parentElement.removeChild(deleteElement);

        reduceTreeSiblingMultiplicities(parentElement, deleteElement);

        this.getMainInstance().cleanCache();

        triggerTriggerables(deleteRef);
        return newIndex;
    }

    /**
     * When a repeat is deleted, we need to reduce the multiplicities of its siblings that were higher than it
     * by one.
     *
     * @param parentElement the parent of the deleted element
     * @param deleteElement the deleted element
     */
    private void reduceTreeSiblingMultiplicities(TreeElement parentElement, TreeElement deleteElement) {
        int childMult = deleteElement.getMult();
        // update multiplicities of other child nodes
        for (int i = 0; i < parentElement.getNumChildren(); i++) {
            TreeElement child = parentElement.getChildAt(i);
            // We also need to check that this element matches the deleted element (besides multiplicity)
            // in the case where the deleted repeat's parent isn't a subgroup
            if (child.doFieldsMatch(deleteElement) && child.getMult() > childMult) {
                child.setMult(child.getMult() - 1);
            }
        }
    }

    public void createNewRepeat(FormIndex index) throws InvalidReferenceException {
        TreeReference repeatContextRef = getChildInstanceRef(index);
        TreeElement template = mainInstance.getTemplate(repeatContextRef);

        mainInstance.copyNode(template, repeatContextRef);

        // Fire jr-insert events before "calculate"s
        triggeredDuringInsert.removeAllElements();
        actionController.triggerActionsFromEvent(Action.EVENT_JR_INSERT, this, repeatContextRef, this);

        // trigger conditions that depend on the creation of this new node
        triggerTriggerables(repeatContextRef);

        // trigger conditions for the node (and sub-nodes)
        initTriggerablesRootedBy(repeatContextRef, triggeredDuringInsert);
    }

    @Override
    public void processResultOfAction(TreeReference refSetByAction, String event) {
        if (Action.EVENT_JR_INSERT.equals(event)) {
            Vector<Triggerable> triggerables =
                    triggerIndex.get(refSetByAction.genericize());
            if (triggerables != null) {
                for (Triggerable elem : triggerables) {
                    triggeredDuringInsert.addElement(elem);
                }
            }
        }
    }

    public boolean isRepeatRelevant(TreeReference repeatRef) {
        boolean relev = true;

        Condition c = conditionRepeatTargetIndex.get(repeatRef.genericize());
        if (c != null) {
            relev = c.evalBool(mainInstance, new EvaluationContext(exprEvalContext, repeatRef));
        }

        //check the relevancy of the immediate parent
        if (relev) {
            TreeElement templNode = mainInstance.getTemplate(repeatRef);
            TreeReference parentPath = templNode.getParent().getRef().genericize();
            TreeElement parentNode = mainInstance.resolveReference(parentPath.contextualize(repeatRef));
            relev = parentNode.isRelevant();
        }

        return relev;
    }

    /**
     * Does the repeat group at the given index enable users to add more items,
     * and if so, has the user reached the item limit?
     *
     * @param repeatRef   Reference pointing to a particular repeat item
     * @param repeatIndex Id for looking up the repeat group
     * @return Do the current constraints on the repeat group allow for adding
     * more children?
     */
    public boolean canCreateRepeat(TreeReference repeatRef, FormIndex repeatIndex) {
        GroupDef repeat = (GroupDef)this.getChild(repeatIndex);

        //Check to see if this repeat can have children added by the user
        if (repeat.noAddRemove) {
            //Check to see if there's a count to use to determine how many children this repeat
            //should have
            if (repeat.getCountReference() != null) {
                int currentMultiplicity = repeatIndex.getElementMultiplicity();

                TreeReference absPathToCount = repeat.getConextualizedCountReference(repeatRef);
                AbstractTreeElement countNode = this.getMainInstance().resolveReference(absPathToCount);
                if (countNode == null) {
                    throw new XPathTypeMismatchException("Could not find the location " +
                            absPathToCount.toString() + " where the repeat at " +
                            repeatRef.toString(false) + " is looking for its count");
                }
                //get the total multiplicity possible
                IAnswerData boxedCount = countNode.getValue();
                int count;
                if (boxedCount == null) {
                    count = 0;
                } else {
                    try {
                        count = ((Integer)new IntegerData().cast(boxedCount.uncast()).getValue());
                    } catch (IllegalArgumentException iae) {
                        throw new XPathTypeMismatchException("The repeat count value \"" +
                                boxedCount.uncast().getString() +
                                "\" at " + absPathToCount.toString() +
                                " must be a number!");
                    }
                }

                if (count <= currentMultiplicity) {
                    return false;
                }
            } else {
                //Otherwise the user can never add repeat instances
                return false;
            }
        }

        //TODO: If we think the node is still relevant, we also need to figure out a way to test that assumption against
        //the repeat's constraints.

        return true;
    }

    public void copyItemsetAnswer(QuestionDef q, TreeElement targetNode, IAnswerData data) throws InvalidReferenceException {
        ItemsetBinding itemset = q.getDynamicChoices();
        TreeReference targetRef = targetNode.getRef();
        TreeReference destRef = itemset.getDestRef().contextualize(targetRef);

        Vector<Selection> selections = null;
        Vector<String> selectedValues = new Vector<>();
        if (data instanceof SelectMultiData) {
            selections = (Vector<Selection>)data.getValue();
        } else if (data instanceof SelectOneData) {
            selections = new Vector<>();
            selections.addElement((Selection)data.getValue());
        }
        if (itemset.valueRef != null) {
            for (int i = 0; i < selections.size(); i++) {
                selectedValues.addElement(selections.elementAt(i).choice.getValue());
            }
        }

        //delete existing dest nodes that are not in the answer selection
        Hashtable<String, TreeElement> existingValues = new Hashtable<>();
        Vector<TreeReference> existingNodes = exprEvalContext.expandReference(destRef);
        for (int i = 0; i < existingNodes.size(); i++) {
            TreeElement node = getMainInstance().resolveReference(existingNodes.elementAt(i));

            if (itemset.valueRef != null) {
                String value = itemset.getRelativeValue().evalReadable(this.getMainInstance(), new EvaluationContext(exprEvalContext, node.getRef()));
                if (selectedValues.contains(value)) {
                    existingValues.put(value, node); //cache node if in selection and already exists
                }
            }

            //delete from target
            targetNode.removeChild(node);
        }

        //copy in nodes for new answer; preserve ordering in answer
        for (int i = 0; i < selections.size(); i++) {
            Selection s = selections.elementAt(i);
            SelectChoice ch = s.choice;

            TreeElement cachedNode = null;
            if (itemset.valueRef != null) {
                String value = ch.getValue();
                if (existingValues.containsKey(value)) {
                    cachedNode = existingValues.get(value);
                }
            }

            if (cachedNode != null) {
                cachedNode.setMult(i);
                targetNode.addChild(cachedNode);
            } else {
                getMainInstance().copyItemsetNode(ch.copyNode, destRef, this);
            }
        }

        // trigger conditions that depend on the creation of these new nodes
        triggerTriggerables(destRef);

        // initialize conditions for the node (and sub-nodes)
        // NOTE PLM: the following trigger initialization doesn't cascade to
        // children because it is behaving like trigger initalization for new
        // repeat entries.  If we begin actually using this method, the trigger
        // cascading logic should be fixed.
        initTriggerablesRootedBy(destRef, new Vector<Triggerable>());
        // not 100% sure this will work since destRef is ambiguous as the last
        // step, but i think it's supposed to work
    }

    /**
     * Add a Condition to the form's Collection.
     */
    public Triggerable addTriggerable(Triggerable t) {
        int existingIx = triggerables.indexOf(t);
        if (existingIx != -1) {
            // One node may control access to many nodes; this means many nodes
            // effectively have the same condition. Let's identify when
            // conditions are the same, and store and calculate it only once.

            // nov-2-2011: ctsims - We need to merge the context nodes together
            // whenever we do this (finding the highest common ground between
            // the two), otherwise we can end up failing to trigger when the
            // ignored context exists and the used one doesn't

            Triggerable existingTriggerable = triggerables.get(existingIx);

            existingTriggerable.contextRef = existingTriggerable.contextRef.intersect(t.contextRef);

            return existingTriggerable;

            // NOTE: if the contextRef is unnecessarily deep, the condition
            // will be evaluated more times than needed. Perhaps detect when
            // 'identical' condition has a shorter contextRef, and use that one
            // instead?
        } else {
            // The triggerable isn't being added in any order, so topological
            // sorting has been disrupted
            triggerables.add(t);

            for (TreeReference trigger : t.getTriggers()) {
                TreeReference predicatelessTrigger = t.widenContextToAndClearPredicates(trigger);
                if (!triggerIndex.containsKey(predicatelessTrigger)) {
                    triggerIndex.put(predicatelessTrigger.clone(), new Vector<Triggerable>());
                }
                Vector<Triggerable> triggered = triggerIndex.get(predicatelessTrigger);
                if (!triggered.contains(t)) {
                    triggered.addElement(t);
                }
            }

            return t;
        }
    }

    /**
     * Dependency-sorted enumerator for the triggerables present in the form.
     *
     * @return Enumerator of triggerables such that when an element X precedes
     * Y then X doesn't have any references that are dependent on Y.
     */
    public Iterator<Triggerable> getTriggerables() {
        return triggerables.iterator();
    }

    /**
     * @return All references in the form that are depended on by
     * calculate/relevancy conditions.
     */
    public Iterator<TreeReference> refWithTriggerDependencies() {
        return triggerIndex.keySet().iterator();
    }

    /**
     * Get the triggerable conditions, like relevancy/calculate, that depend on
     * the given reference.
     *
     * @param ref An absolute reference that is used in relevancy/calculate
     *            expressions.
     * @return All the triggerables that depend on the given reference.
     */
    public Vector conditionsTriggeredByRef(TreeReference ref) {
        return triggerIndex.get(ref);
    }

    /**
     * Finalize the DAG associated with the form's triggered conditions. This will create
     * the appropriate ordering and dependencies to ensure the conditions will be evaluated
     * in the appropriate orders.
     *
     * @throws IllegalStateException If the trigger ordering contains an illegal cycle and the
     *                               triggers can't be laid out appropriately
     */
    public void finalizeTriggerables() throws IllegalStateException {
        ArrayList<Pair<Triggerable, Triggerable>> partialOrdering = new ArrayList<>();
        buildPartialOrdering(partialOrdering);

        ArrayList<Triggerable> vertices = new ArrayList<>(triggerables);
        triggerables.clear();

        while (!vertices.isEmpty()) {
            List<Triggerable> roots = buildRootNodes(vertices, partialOrdering);

            if (roots.isEmpty()) {
                // if no root nodes while graph still has nodes, graph has cycles
                throwGraphCyclesException(vertices);
            }

            setOrderOfTriggerable(roots, vertices, partialOrdering);
        }

        // At this point triggerables should be topologically sorted (according
        // to Drew)

        buildConditionRepeatTargetIndex();
    }

    private void buildPartialOrdering(List<Pair<Triggerable, Triggerable>> partialOrdering) {
        for (Triggerable t : triggerables) {
            ArrayList<Triggerable> deps = new ArrayList<>();
            fillTriggeredElements(t, deps, false);

            for (Triggerable u : deps) {
                partialOrdering.add(new Pair<>(t, u));
            }
        }
    }

    private static List<Triggerable> buildRootNodes(List<Triggerable> vertices,
                                                    List<Pair<Triggerable, Triggerable>> partialOrdering) {
        ArrayList<Triggerable> roots = new ArrayList<>(vertices);

        for (Pair<Triggerable, Triggerable> edge : partialOrdering) {
            edge.second.updateStopContextualizingAtFromDominator(edge.first);
            roots.remove(edge.second);
        }
        return roots;
    }

    private ArrayList<TreeReference> getTreeReferenceAndChildren(TreeReference reference) {
        ArrayList<TreeReference> updatedNodes = new ArrayList<>();
        updatedNodes.add(reference);
        updatedNodes = findCascadeReferences(reference, updatedNodes);
        return updatedNodes;
    }

    private void throwGraphCyclesException(List<Triggerable> vertices) {
        Vector edges = new Vector<TreeReference[]>();
        for (Triggerable outerTriggerables : vertices) {
            for (TreeReference outerReference : outerTriggerables.getTargets()) {
                // Get child refs because children are affected by parents
                ArrayList<TreeReference> updatedNodes = getTreeReferenceAndChildren(outerReference);
                if (updatedNodes != null) {
                    for (TreeReference innerReference : updatedNodes) {
                        Vector<Triggerable> triggered = (Vector<Triggerable>)conditionsTriggeredByRef(innerReference);
                        if (triggered != null) {
                            for (Triggerable trig : triggered) {
                                if (!innerReference.equals(outerReference)) {
                                    // We are dealing with a child and parent, so add an edge between the parent
                                    // and child for clarity in the error message.
                                    edges.add(new TreeReference[]{outerReference, innerReference});
                                }
                                // Add all the targets of the of the triggered
                                for (TreeReference reference : trig.getTargets()) {
                                    edges.add(new TreeReference[]{innerReference, reference});
                                }
                            }
                        }
                    }
                }
            }
        }
        throw new IllegalStateException(new ShortestCycleAlgorithm(edges).getCycleErrorMessage());
    }

    private void setOrderOfTriggerable(List<Triggerable> roots,
                                       List<Triggerable> vertices,
                                       List<Pair<Triggerable, Triggerable>> partialOrdering) {
        for (Triggerable root : roots) {
            triggerables.add(root);
            vertices.remove(root);
        }
        for (int i = partialOrdering.size() - 1; i >= 0; i--) {
            Pair<Triggerable, Triggerable> edge = partialOrdering.get(i);
            if (roots.contains(edge.first)) {
                partialOrdering.remove(i);
            }
        }
    }

    private void buildConditionRepeatTargetIndex() {
        conditionRepeatTargetIndex = new HashMap<>();
        for (Triggerable t : triggerables) {
            if (t instanceof Condition) {
                for (TreeReference target : t.getTargets()) {
                    if (mainInstance.getTemplate(target) != null) {
                        conditionRepeatTargetIndex.put(target, (Condition)t);
                    }
                }
            }
        }
    }

    /**
     * Get all of the elements which will need to be evaluated (in order) when
     * the triggerable is fired.
     *
     * @param destination       (mutated) Will have triggerables added to it.
     * @param isRepeatEntryInit Don't cascade triggers to children when
     *                          initializing a new repeat entry.  Repeat entry
     *                          children have already been queued to be
     *                          triggered.
     */
    private void fillTriggeredElements(Triggerable t,
                                       List<Triggerable> destination,
                                       boolean isRepeatEntryInit) {
        if (t.canCascade()) {
            for (TreeReference target : t.getTargets()) {
                ArrayList<TreeReference> updatedNodes = new ArrayList<>();
                updatedNodes.add(target);
                // Repeat sub-elements have already been added to 'destination'
                // when we grabbed all triggerables that target children of the
                // repeat entry (via initTriggerablesRootedBy). Hence skip them
                if (!isRepeatEntryInit && t.isCascadingToChildren()) {
                    updatedNodes = findCascadeReferences(target, updatedNodes);
                }

                addTriggerablesTargetingNodes(updatedNodes, destination);
            }
        }
    }

    /**
     * Gather list of generic references to children of a target reference for
     * a triggerable that cascades to its children. This is needed when, for
     * example, changing the relevancy of the target will require the triggers
     * pointing to children be recalcualted.
     *
     * @param target       Gather children of this by using a template or
     *                     manually traversing the tree
     * @param updatedNodes (potentially mutated) Gets generic child references
     *                     added to it.
     * @return Potentially cached version of updatedNodes argument that
     * contains the target and generic references to the children it might
     * cascade to.
     */
    private ArrayList<TreeReference> findCascadeReferences(TreeReference target,
                                                           ArrayList<TreeReference> updatedNodes) {
        ArrayList<TreeReference> cachedNodes = cachedCascadingChildren.retrieve(target);
        if (cachedNodes == null) {
            if (target.getMultLast() == TreeReference.INDEX_ATTRIBUTE) {
                // attributes don't have children that might change under
                // contextualization
                cachedCascadingChildren.register(target, updatedNodes);
            } else {
                Vector<TreeReference> expandedRefs = exprEvalContext.expandReference(target, true);
                if (expandedRefs.size() > 0) {
                    AbstractTreeElement template = mainInstance.getTemplatePath(target);
                    if (template != null) {
                        addChildrenOfElement(template, updatedNodes);
                        cachedCascadingChildren.register(target, updatedNodes);
                    } else {
                        // NOTE PLM: entirely possible this can be removed if
                        // the getTemplatePath code is updated to handle
                        // heterogeneous paths.  Set a breakpoint here and run
                        // the test suite to see an example
                        // NOTE PLM: Though I'm pretty sure we could cache
                        // this, I'm going to avoid doing so because I'm unsure
                        // whether it is possible for children that are
                        // cascaded to will change when expandedRefs changes
                        // due to new data being added.
                        addChildrenOfReference(expandedRefs, updatedNodes);
                    }
                }
            }
        } else {
            updatedNodes = cachedNodes;
        }
        return updatedNodes;
    }

    /**
     * Resolve the expanded references and gather their generic children and
     * attributes into the genericRefs list.
     */
    private void addChildrenOfReference(List<TreeReference> expandedRefs,
                                        List<TreeReference> genericRefs) {
        for (TreeReference ref : expandedRefs) {
            addChildrenOfElement(exprEvalContext.resolveReference(ref), genericRefs);
        }
    }

    /**
     * Gathers generic children and attribute references for the provided
     * element into the genericRefs list.
     */
    private static void addChildrenOfElement(AbstractTreeElement treeElem,
                                             List<TreeReference> genericRefs) {
        // recursively add children of element
        for (int i = 0; i < treeElem.getNumChildren(); ++i) {
            AbstractTreeElement child = treeElem.getChildAt(i);
            TreeReference genericChild = child.getRef().genericize();
            if (!genericRefs.contains(genericChild)) {
                genericRefs.add(genericChild);
            }
            addChildrenOfElement(child, genericRefs);
        }

        // add all the attributes of this element
        for (int i = 0; i < treeElem.getAttributeCount(); ++i) {
            AbstractTreeElement child =
                    treeElem.getAttribute(treeElem.getAttributeNamespace(i),
                            treeElem.getAttributeName(i));
            TreeReference genericChild = child.getRef().genericize();
            if (!genericRefs.contains(genericChild)) {
                genericRefs.add(genericChild);
            }
        }
    }

    private void addTriggerablesTargetingNodes(List<TreeReference> updatedNodes,
                                               List<Triggerable> destination) {
        //Now go through each of these updated nodes (generally just 1 for a normal calculation,
        //multiple nodes if there's a relevance cascade.
        for (TreeReference ref : updatedNodes) {
            //Check our index to see if that target is a Trigger for other conditions
            //IE: if they are an element of a different calculation or relevancy calc

            //We can't make this reference generic before now or we'll lose the target information,
            //so we'll be more inclusive than needed and see if any of our triggers are keyed on
            //the predicate-less path of this ref
            TreeReference predicatelessRef = ref;
            if (ref.hasPredicates()) {
                predicatelessRef = ref.removePredicates();
            }
            Vector<Triggerable> triggered = triggerIndex.get(predicatelessRef);

            if (triggered != null) {
                //If so, walk all of these triggerables that we found
                for (Triggerable triggerable : triggered) {
                    //And add them to the queue if they aren't there already
                    if (!destination.contains(triggerable)) {
                        destination.add(triggerable);
                    }
                }
            }
        }
    }

    /**
     * Enables debug traces in this form, which can be requested as a map after
     * this call has been performed. Debug traces will be available until they
     * are explicitly disabled.
     *
     * This call also re-executes all triggerables in debug mode to make their
     * current traces available.
     *
     * Must be called after this form is initialized.
     */
    public void enableDebugTraces() {
        if (!mDebugModeEnabled) {
            for (Triggerable t : triggerables) {
                t.setDebug(true);
            }

            // Re-execute all triggerables to collect traces
            initAllTriggerables();
            mDebugModeEnabled = true;
        }
    }

    /**
     * Disable debug tracing for this form. Debug traces will no longer be
     * available after this call.
     */
    public void disableDebugTraces() {
        if (mDebugModeEnabled) {
            for (Triggerable t : triggerables) {
                t.setDebug(false);
            }
            mDebugModeEnabled = false;
        }
    }

    /**
     * Aggregates a map of evaluation traces collected by the form's
     * triggerables.
     *
     * @return A mapping from TreeReferences to a set of evaluation traces. The
     * traces are separated out by triggerable category (calculate, relevant,
     * etc) and represent the execution of the last expression that was
     * executed for that trigger.
     * @throws IllegalStateException If debugging has not been enabled.
     */
    public Hashtable<TreeReference, Hashtable<String, EvaluationTrace>> getDebugTraceMap()
            throws IllegalStateException {

        if (!mDebugModeEnabled) {
            throw new IllegalStateException("Debugging is not enabled");
        }

        // TODO: sure would be nice to be able to cache this at some point, but
        // will have to have a way to invalidate by trigger or something
        Hashtable<TreeReference, Hashtable<String, EvaluationTrace>> debugInfo =
                new Hashtable<>();

        for (Triggerable t : triggerables) {
            Hashtable<TreeReference, EvaluationTrace> triggerOutputs = t.getEvaluationTraces();

            for (Enumeration e = triggerOutputs.keys(); e.hasMoreElements(); ) {
                TreeReference elementRef = (TreeReference)e.nextElement();
                String label = t.getDebugLabel();
                Hashtable<String, EvaluationTrace> traces = debugInfo.get(elementRef);
                if (traces == null) {
                    traces = new Hashtable<>();
                }
                traces.put(label, triggerOutputs.get(elementRef));
                debugInfo.put(elementRef, traces);
            }
        }

        return debugInfo;
    }

    private void initAllTriggerables() {
        // Use all triggerables because we can assume they are rooted by rootRef
        TreeReference rootRef = TreeReference.rootRef();

        Vector<Triggerable> applicable = new Vector<>();
        for (Triggerable triggerable : triggerables) {
            applicable.addElement(triggerable);
        }

        evaluateTriggerables(applicable, rootRef, false);
    }

    /**
     * Evaluate triggerables targeting references that are children of the
     * provided newly created (repeat instance) ref.  Ignore all triggerables
     * that were already fired by processing the jr-insert action. Ignored
     * triggerables can still be fired if a dependency is modified.
     *
     * @param triggeredDuringInsert Triggerables that don't need to be fired
     *                              because they have already been fired while processing insert events
     */
    private void initTriggerablesRootedBy(TreeReference rootRef,
                                          Vector<Triggerable> triggeredDuringInsert) {
        TreeReference genericRoot = rootRef.genericize();

        Vector<Triggerable> applicable = new Vector<>();
        for (Triggerable triggerable : triggerables) {
            for (TreeReference target : triggerable.getTargets()) {
                if (genericRoot.isParentOf(target, false)) {
                    if (!triggeredDuringInsert.contains(triggerable)) {
                        applicable.addElement(triggerable);
                        break;
                    }
                }
            }
        }

        evaluateTriggerables(applicable, rootRef, true);
    }

    /**
     * The entry point for the DAG cascade after a value is changed in the model.
     *
     * @param ref The full contextualized unambiguous reference of the value that was
     *            changed.
     */
    public void triggerTriggerables(TreeReference ref) {
        // turn unambiguous ref into a generic ref to identify what nodes
        // should be triggered by this reference changing
        TreeReference genericRef = ref.genericize();

        // get triggerables which are activated by the generic reference
        Vector<Triggerable> triggered = triggerIndex.get(genericRef);
        if (triggered != null) {
            Vector<Triggerable> triggeredCopy = new Vector<>(triggered);

            evaluateTriggerables(triggeredCopy, ref, false);
        }
    }

    /**
     * Step 2 in evaluating DAG computation updates from a value being changed
     * in the instance. This step is responsible for taking the root set of
     * directly triggered conditions, identifying which conditions should
     * further be triggered due to their update, and then dispatching all of
     * the evaluations.
     *
     * @param tv                A vector of all of the trigerrables directly
     *                          triggered by the value changed. Will be mutated
     *                          by this method.
     * @param anchorRef         The reference to original value that was updated
     * @param isRepeatEntryInit Don't cascade triggers to children when
     *                          initializing a new repeat entry.  Repeat entry
     *                          children have already been queued to be
     *                          triggered.
     */
    private void evaluateTriggerables(List<Triggerable> tv,
                                      TreeReference anchorRef,
                                      boolean isRepeatEntryInit) {
        // Update the list of triggerables that need to be evaluated.
        for (int i = 0; i < tv.size(); i++) {
            // NOTE PLM: tv may grow in size through iteration.
            Triggerable t = tv.get(i);
            fillTriggeredElements(t, tv, isRepeatEntryInit);
        }

        // tv should now contain all of the triggerable components which are
        // going to need to be addressed by this update.
        // 'triggerables' is topologically-ordered by dependencies, so evaluate
        // the triggerables in 'tv' in the order they appear in 'triggerables'
        for (Triggerable triggerable : triggerables) {
            if (tv.contains(triggerable)) {
                evaluateTriggerable(triggerable, anchorRef);
            }
        }
    }

    /**
     * Step 3 in DAG cascade. evaluate the individual triggerable expressions
     * against the anchor (the value that changed which triggered
     * recomputation)
     *
     * @param triggerable The triggerable to be updated
     * @param anchorRef   The reference to the value which was changed.
     */
    private void evaluateTriggerable(Triggerable triggerable, TreeReference anchorRef) {
        // Contextualize the reference used by the triggerable against the anchor
        TreeReference contextRef = triggerable.narrowContextBy(anchorRef);

        // Now identify all of the fully qualified nodes which this triggerable
        // updates. (Multiple nodes can be updated by the same trigger)
        Vector<TreeReference> expandedReferences = exprEvalContext.expandReference(contextRef);

        for (TreeReference treeReference : expandedReferences) {
            triggerable.apply(mainInstance, exprEvalContext, treeReference, this);
        }
    }

    public boolean evaluateConstraint(TreeReference ref, IAnswerData data) {
        if (data instanceof InvalidData) {
            return false;
        }

        if (data == null) {
            return true;
        }

        TreeElement node = mainInstance.resolveReference(ref);
        Constraint c = node.getConstraint();

        if (c == null) {
            return true;
        }
        EvaluationContext ec = new EvaluationContext(exprEvalContext, ref);
        ec.isConstraint = true;
        ec.candidateValue = data;

        return c.constraint.eval(mainInstance, ec);
    }

    public void setEvaluationContext(EvaluationContext ec) {
        ec = new EvaluationContext(mainInstance, formInstances, ec);
        initEvalContext(ec);
        if (useExpressionCaching) {
            ec.enableExpressionCaching();
        }
        this.exprEvalContext = ec;
    }

    public EvaluationContext getEvaluationContext() {
        return this.exprEvalContext;
    }

    private void initEvalContext(EvaluationContext ec) {
        if (!ec.getFunctionHandlers().containsKey("jr:itext")) {
            final FormDef f = this;
            ec.addFunctionHandler(new IFunctionHandler() {
                @Override
                public String getName() {
                    return "jr:itext";
                }

                @Override
                public Object eval(Object[] args, EvaluationContext ec) {
                    String textID = (String)args[0];
                    try {
                        //SUUUUPER HACKY
                        String form = ec.getOutputTextForm();
                        if (form != null) {
                            textID = textID + ";" + form;
                            String result = f.getLocalizer().getRawText(f.getLocalizer().getLocale(), textID);
                            return result == null ? "" : result;
                        } else {
                            String text = f.getLocalizer().getText(textID);
                            return text == null ? "[itext:" + textID + "]" : text;
                        }
                    } catch (NoSuchElementException nsee) {
                        return "[nolocale]";
                    }
                }

                @Override
                public Vector getPrototypes() {
                    Class[] proto = {String.class};
                    Vector<Class[]> v = new Vector<>();
                    v.addElement(proto);
                    return v;
                }

                @Override
                public boolean rawArgs() {
                    return false;
                }
            });
        }

        /* function to reverse a select value into the display label for that choice in the question it came from
         *
         * arg 1: select value
         * arg 2: string xpath referring to origin question; must be absolute path
         *
         * this won't work at all if the original label needed to be processed/calculated in some way (<output>s, etc.) (is this even allowed?)
         * likely won't work with multi-media labels
         * _might_ work for itemsets, but probably not very well or at all; could potentially work better if we had some context info
         * DOES work with localization
         *
         * it's mainly intended for the simple case of reversing a question with compile-time-static fields, for use inside an <output>
         */
        if (!ec.getFunctionHandlers().containsKey("jr:choice-name")) {
            final FormDef f = this;
            ec.addFunctionHandler(new IFunctionHandler() {
                @Override
                public String getName() {
                    return "jr:choice-name";
                }

                @Override
                public Object eval(Object[] args, EvaluationContext ec) {
                    try {
                        String value = (String)args[0];
                        String questionXpath = (String)args[1];
                        TreeReference ref = RestoreUtils.ref(questionXpath);

                        QuestionDef q = FormDef.findQuestionByRef(ref, f);
                        if (q == null || (q.getControlType() != Constants.CONTROL_SELECT_ONE &&
                                q.getControlType() != Constants.CONTROL_SELECT_MULTI)) {
                            return "";
                        }

                        System.out.println("here!!");

                        Vector<SelectChoice> choices = q.getChoices();
                        for (SelectChoice ch : choices) {
                            if (ch.getValue().equals(value)) {
                                //this is really not ideal. we should hook into the existing code (FormEntryPrompt) for pulling
                                //display text for select choices. however, it's hard, because we don't really have
                                //any context to work with, and all the situations where that context would be used
                                //don't make sense for trying to reverse a select value back to a label in an unrelated
                                //expression

                                String textID = ch.getTextID();
                                if (textID != null) {
                                    return f.getLocalizer().getText(textID);
                                } else {
                                    return ch.getLabelInnerText();
                                }
                            }
                        }
                        return "";
                    } catch (Exception e) {
                        throw new WrappedException("error in evaluation of xpath function [choice-name]", e);
                    }
                }

                @Override
                public Vector getPrototypes() {
                    Class[] proto = {String.class, String.class};
                    Vector<Class[]> v = new Vector<>();
                    v.addElement(proto);
                    return v;
                }

                @Override
                public boolean rawArgs() {
                    return false;
                }
            });
        }
    }

    public void enableExpressionCaching() {
        useExpressionCaching = true;
    }

    public String fillTemplateString(String template, TreeReference contextRef) {
        return fillTemplateString(template, contextRef, new Hashtable());
    }

    /**
     * Performs substitutions on place-holder template from form text by
     * evaluating args in template using the current context.
     *
     * @param template   String
     * @param contextRef TreeReference
     * @param variables  Hashtable<String, ?>
     * @return String with the all args in the template filled with appropriate
     * context values.
     */
    public String fillTemplateString(String template, TreeReference contextRef, Hashtable<String, ?> variables) {
        // argument to value mapping
        Hashtable<String, String> args = new Hashtable<>();

        int depth = 0;
        // grab all template arguments that need to have substitutions performed
        Vector outstandingArgs = Localizer.getArgs(template);

        String templateAfterSubstitution;

        // Step through outstandingArgs from the template, looking up the value
        // they map to, evaluating that under the evaluation context and
        // storing in the local args mapping.
        // Then perform substitutions over the template until a fixpoint is found
        while (outstandingArgs.size() > 0) {
            for (int i = 0; i < outstandingArgs.size(); i++) {
                String argName = (String)outstandingArgs.elementAt(i);
                // lookup value an arg points to if it isn't in our local mapping
                if (!args.containsKey(argName)) {
                    int ix = -1;
                    try {
                        ix = Integer.parseInt(argName);
                    } catch (NumberFormatException nfe) {
                        System.err.println("Warning: expect arguments to be numeric [" + argName + "]");
                    }

                    if (ix < 0 || ix >= outputFragments.size()) {
                        continue;
                    }

                    IConditionExpr expr = (IConditionExpr)outputFragments.elementAt(ix);
                    EvaluationContext ec = new EvaluationContext(exprEvalContext, contextRef);
                    ec.setOriginalContext(contextRef);
                    ec.setVariables(variables);
                    String value = expr.evalReadable(this.getMainInstance(), ec);
                    args.put(argName, value);
                }
            }

            templateAfterSubstitution = Localizer.processArguments(template, args);

            // The last substitution made no progress, probably because the
            // argument isn't in outputFragments, so stop looping and
            // attempting more subs!
            if (template.equals(templateAfterSubstitution)) {
                return template;
            }

            template = templateAfterSubstitution;

            // Since strings being substituted might themselves have arguments that
            // need to be further substituted, we must recompute the unperformed
            // substitutions and continue to loop.
            outstandingArgs = Localizer.getArgs(template);

            if (depth++ >= TEMPLATING_RECURSION_LIMIT) {
                throw new RuntimeException("Dependency cycle in <output>s; recursion limit exceeded!!");
            }
        }

        return template;
    }

    public void populateDynamicChoices(ItemsetBinding itemset, TreeReference curQRef){
        ItemSetUtils.populateDynamicChoices(itemset, curQRef, exprEvalContext, getMainInstance(), mProfilingEnabled);
    }

    public String toString() {
        return getTitle();
    }

    public void postProcessInstance() {
        if (!isCompletedInstance) {
            actionController.triggerActionsFromEvent(Action.EVENT_XFORMS_REVALIDATE, this);
        }
    }

    /**
     * Reads the form definition object from the supplied stream.
     *
     * Requires that the instance has been set to a prototype of the instance that
     * should be used for deserialization.
     */
    @Override
    public void readExternal(DataInputStream dis, PrototypeFactory pf) throws IOException, DeserializationException {
        setID(ExtUtil.readInt(dis));
        setName(ExtUtil.nullIfEmpty(ExtUtil.readString(dis)));
        setTitle((String)ExtUtil.read(dis, new ExtWrapNullable(String.class), pf));
        setChildren((Vector)ExtUtil.read(dis, new ExtWrapListPoly(), pf));
        setInstance((FormInstance)ExtUtil.read(dis, FormInstance.class, pf));

        setLocalizer((Localizer)ExtUtil.read(dis, new ExtWrapNullable(Localizer.class), pf));

        Vector vcond = (Vector)ExtUtil.read(dis, new ExtWrapList(Condition.class), pf);
        for (Enumeration e = vcond.elements(); e.hasMoreElements(); ) {
            addTriggerable((Condition)e.nextElement());
        }
        Vector vcalc = (Vector)ExtUtil.read(dis, new ExtWrapList(Recalculate.class), pf);
        for (Enumeration e = vcalc.elements(); e.hasMoreElements(); ) {
            addTriggerable((Recalculate)e.nextElement());
        }
        finalizeTriggerables();

        outputFragments = (Vector)ExtUtil.read(dis, new ExtWrapListPoly(), pf);

        submissionProfiles = (Hashtable<String, SubmissionProfile>)ExtUtil.read(dis, new ExtWrapMap(String.class, SubmissionProfile.class), pf);

        formInstances = (Hashtable<String, DataInstance>)ExtUtil.read(dis, new ExtWrapMap(String.class, new ExtWrapTagged()), pf);

        extensions = (Vector)ExtUtil.read(dis, new ExtWrapListPoly(), pf);

        setEvaluationContext(new EvaluationContext(null));
        actionController = (ActionController)ExtUtil.read(dis, ActionController.class, pf);
    }

    /**
     * meant to be called after deserialization and initialization of handlers
     *
     * @param newInstance         true if the form is to be used for a new entry interaction,
     *                            false if it is using an existing IDataModel
     * @param isCompletedInstance true if this is an already completed instance we are editing
     *                            (presumably in HQ) - so don't fire end of form event.
     */
    public void initialize(boolean newInstance, boolean isCompletedInstance,
                           InstanceInitializationFactory factory) {
        initialize(newInstance, isCompletedInstance, factory, null, false);
    }

    public void initialize(boolean newInstance, InstanceInitializationFactory factory) {
        initialize(newInstance, false, factory, null, false);
    }

    public void initialize(boolean newInstance, InstanceInitializationFactory factory, String locale,
                           boolean isReadOnly) {
        initialize(newInstance, false, factory, locale, isReadOnly);
    }

    /**
     * meant to be called after deserialization and initialization of handlers
     *
     * @param newInstance true if the form is to be used for a new entry interaction,
     *                    false if it is using an existing IDataModel
     * @param locale      The default locale in the current environment, if provided. Can be null
     *                    to rely on the form's internal default.
     */
    public void initialize(boolean newInstance, boolean isCompletedInstance,
                           InstanceInitializationFactory factory, String locale, boolean isReadOnly) {
        for (Enumeration en = formInstances.keys(); en.hasMoreElements(); ) {
            String instanceId = (String)en.nextElement();
            DataInstance instance = formInstances.get(instanceId);
            formInstances.put(instanceId, instance.initialize(factory, instanceId));
        }

        initLocale(locale);

        if (newInstance) {
            // only dispatch on a form's first opening, not subsequent loadings
            // of saved instances. Ensures setvalues triggered by xform-ready,
            // useful for recording form start dates.
            actionController.triggerActionsFromEvent(Action.EVENT_XFORMS_READY, this);
        }
        this.isCompletedInstance = isCompletedInstance;
        if (!isReadOnly) {
            initAllTriggerables();
        }
    }

    private void initLocale(String locale) {
        if (localizer != null) {
            if (locale == null || !localizer.hasLocale(locale)) {
                if (localizer.getLocale() == null) {
                    localizer.setToDefault();
                }
            } else {
                localizer.setLocale(locale);
            }
        }
    }

    /**
     * Writes the form definition object to the supplied stream.
     */
    @Override
    public void writeExternal(DataOutputStream dos) throws IOException {
        ExtUtil.writeNumeric(dos, getID());
        ExtUtil.writeString(dos, ExtUtil.emptyIfNull(getName()));
        ExtUtil.write(dos, new ExtWrapNullable(getTitle()));
        ExtUtil.write(dos, new ExtWrapListPoly(getChildren()));
        ExtUtil.write(dos, getMainInstance());
        ExtUtil.write(dos, new ExtWrapNullable(localizer));

        Vector<Condition> conditions = new Vector<>();
        Vector<Recalculate> recalcs = new Vector<>();
        for (Triggerable t : triggerables) {
            if (t instanceof Condition) {
                conditions.addElement((Condition)t);
            } else if (t instanceof Recalculate) {
                recalcs.addElement((Recalculate)t);
            }
        }
        ExtUtil.write(dos, new ExtWrapList(conditions));
        ExtUtil.write(dos, new ExtWrapList(recalcs));

        ExtUtil.write(dos, new ExtWrapListPoly(outputFragments));
        ExtUtil.write(dos, new ExtWrapMap(submissionProfiles));

        //for support of multi-instance forms

        ExtUtil.write(dos, new ExtWrapMap(formInstances, new ExtWrapTagged()));
        ExtUtil.write(dos, new ExtWrapListPoly(extensions));
        ExtUtil.write(dos, actionController);
    }

    public void collapseIndex(FormIndex index,
                              Vector<Integer> indexes,
                              Vector<Integer> multiplicities,
                              Vector<IFormElement> elements) {
        if (!index.isInForm()) {
            return;
        }

        IFormElement element = this;
        while (index != null) {
            int i = index.getLocalIndex();
            element = element.getChild(i);

            indexes.addElement(DataUtil.integer(i));
            multiplicities.addElement(DataUtil.integer(index.getInstanceIndex() == -1 ? 0 : index.getInstanceIndex()));
            elements.addElement(element);

            index = index.getNextLevel();
        }
    }

    public FormIndex buildIndex(Vector<Integer> indexes, Vector<Integer> multiplicities, Vector<IFormElement> elements) {
        FormIndex cur = null;
        Vector<Integer> curMultiplicities = new Vector<>();
        for (int j = 0; j < multiplicities.size(); ++j) {
            curMultiplicities.addElement(multiplicities.elementAt(j));
        }

        Vector<IFormElement> curElements = new Vector<>();
        for (int j = 0; j < elements.size(); ++j) {
            curElements.addElement(elements.elementAt(j));
        }

        for (int i = indexes.size() - 1; i >= 0; i--) {
            int ix = indexes.elementAt(i);
            int mult = multiplicities.elementAt(i);

            if (!(elements.elementAt(i) instanceof GroupDef && ((GroupDef)elements.elementAt(i)).isRepeat())) {
                mult = -1;
            }

            cur = new FormIndex(cur, ix, mult, getChildInstanceRef(curElements, curMultiplicities));
            curMultiplicities.removeElementAt(curMultiplicities.size() - 1);
            curElements.removeElementAt(curElements.size() - 1);
        }
        return cur;
    }

    public int getNumRepetitions(FormIndex index) {
        Vector<Integer> indexes = new Vector<>();
        Vector<Integer> multiplicities = new Vector<>();
        Vector<IFormElement> elements = new Vector<>();

        if (!index.isInForm()) {
            throw new RuntimeException("not an in-form index");
        }

        collapseIndex(index, indexes, multiplicities, elements);

        if (!(elements.lastElement() instanceof GroupDef) || !((GroupDef)elements.lastElement()).isRepeat()) {
            throw new RuntimeException("current element not a repeat");
        }

        //so painful
        TreeElement templNode = mainInstance.getTemplate(index.getReference());
        TreeReference parentPath = templNode.getParent().getRef().genericize();
        TreeElement parentNode = mainInstance.resolveReference(parentPath.contextualize(index.getReference()));
        return parentNode.getChildMultiplicity(templNode.getName());
    }

    //repIndex == -1 => next repetition about to be created
    public FormIndex descendIntoRepeat(FormIndex index, int repIndex) {
        int numRepetitions = getNumRepetitions(index);

        Vector<Integer> indexes = new Vector<>();
        Vector<Integer> multiplicities = new Vector<>();
        Vector<IFormElement> elements = new Vector<>();
        collapseIndex(index, indexes, multiplicities, elements);

        if (repIndex == -1) {
            repIndex = numRepetitions;
        } else {
            if (repIndex < 0 || repIndex >= numRepetitions) {
                throw new RuntimeException("selection exceeds current number of repetitions");
            }
        }

        multiplicities.setElementAt(DataUtil.integer(repIndex), multiplicities.size() - 1);

        return buildIndex(indexes, multiplicities, elements);
    }

    @Override
    public int getDeepChildCount() {
        int total = 0;
        Enumeration e = children.elements();
        while (e.hasMoreElements()) {
            total += ((IFormElement)e.nextElement()).getDeepChildCount();
        }
        return total;
    }

    @Override
    public Vector<IFormElement> getChildren() {
        return children;
    }

    @Override
    public void setChildren(Vector<IFormElement> children) {
        this.children = (children == null ? new Vector<IFormElement>() : children);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Override
    public int getID() {
        return id;
    }

    @Override
    public void setID(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Localizer getLocalizer() {
        return localizer;
    }

    public Vector getOutputFragments() {
        return outputFragments;
    }

    public void setOutputFragments(Vector outputFragments) {
        this.outputFragments = outputFragments;
    }

    @Override
    public Object getMetaData(String fieldName) {
        if (fieldName.equals("DESCRIPTOR")) {
            return name;
        }
        if (fieldName.equals("XMLNS")) {
            return ExtUtil.emptyIfNull(mainInstance.schema);
        } else {
            throw new IllegalArgumentException();
        }
    }

    @Override
    public String[] getMetaDataFields() {
        return new String[]{"DESCRIPTOR", "XMLNS"};
    }

    /**
     * Link a deserialized instance back up with its parent FormDef. this allows select/select1 questions to be
     * internationalizable in chatterbox, and (if using CHOICE_INDEX mode) allows the instance to be serialized
     * to xml
     */
    public void attachControlsToInstanceData() {
        attachControlsToInstanceData(getMainInstance().getRoot());
    }

    private void attachControlsToInstanceData(TreeElement node) {
        for (int i = 0; i < node.getNumChildren(); i++) {
            attachControlsToInstanceData(node.getChildAt(i));
        }

        IAnswerData val = node.getValue();
        Vector<Object> selections = null;
        if (val instanceof SelectOneData) {
            selections = new Vector<>();
            selections.addElement(val.getValue());
        } else if (val instanceof SelectMultiData) {
            selections = (Vector<Object>)val.getValue();
        }

        if (selections != null) {
            QuestionDef q = findQuestionByRef(node.getRef(), this);
            if (q == null) {
                throw new RuntimeException("FormDef.attachControlsToInstanceData: can't find question to link");
            }

            if (q.getDynamicChoices() != null) {
                //droos: i think we should do something like initializing the itemset here, so that default answers
                //can be linked to the selectchoices. however, there are complications. for example, the itemset might
                //not be ready to be evaluated at form initialization; it may require certain questions to be answered
                //first. e.g., if we evaluate an itemset and it has no choices, the xform engine will throw an error
                //itemset TODO
            }

            for (int i = 0; i < selections.size(); i++) {
                Selection s = (Selection)selections.elementAt(i);
                s.attachChoice(q);
            }
        }
    }

    public static QuestionDef findQuestionByRef(TreeReference ref, IFormElement fe) {
        if (fe instanceof FormDef) {
            ref = ref.genericize();
        }

        if (fe instanceof QuestionDef) {
            QuestionDef q = (QuestionDef)fe;
            TreeReference bind = FormInstance.unpackReference(q.getBind());
            return (ref.equals(bind) ? q : null);
        } else {
            for (int i = 0; i < fe.getChildren().size(); i++) {
                QuestionDef ret = findQuestionByRef(ref, fe.getChild(i));
                if (ret != null)
                    return ret;
            }
            return null;
        }
    }

    /**
     * Appearance isn't a valid attribute for form, but this method must be included
     * as a result of conforming to the IFormElement interface.
     */
    @Override
    public String getAppearanceAttr() {
        throw new RuntimeException("This method call is not relevant for FormDefs getAppearanceAttr ()");
    }

    /**
     * Appearance isn't a valid attribute for form, but this method must be included
     * as a result of conforming to the IFormElement interface.
     */
    @Override
    public void setAppearanceAttr(String appearanceAttr) {
        throw new RuntimeException("This method call is not relevant for FormDefs setAppearanceAttr()");
    }

    @Override
    public ActionController getActionController() {
        return this.actionController;
    }

    /**
     * Not applicable here.
     */
    @Override
    public String getLabelInnerText() {
        return null;
    }

    /**
     * Not applicable
     */
    @Override
    public String getTextID() {
        return null;
    }

    /**
     * Not applicable
     */
    @Override
    public void setTextID(String textID) {
        throw new RuntimeException("This method call is not relevant for FormDefs [setTextID()]");
    }

    public void setDefaultSubmission(SubmissionProfile profile) {
        submissionProfiles.put(DEFAULT_SUBMISSION_PROFILE, profile);
    }

    public void addSubmissionProfile(String submissionId, SubmissionProfile profile) {
        submissionProfiles.put(submissionId, profile);
    }

    /**
     * @return The submission profile with the given ID.
     */
    public SubmissionProfile getSubmissionProfile(String id) {
        return submissionProfiles.get(id);
    }

    public <X extends XFormExtension> X getExtension(Class<X> extension) {
        for (XFormExtension ex : extensions) {
            if (ex.getClass().isAssignableFrom(extension)) {
                return (X)ex;
            }
        }
        X newEx;
        try {
            newEx = extension.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException("Illegally Structured XForm Extension " + extension.getName());
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Illegally Structured XForm Extension " + extension.getName());
        }
        extensions.addElement(newEx);
        return newEx;
    }

    /**
     * Frees all of the components of this form which are no longer needed once it is completed.
     *
     * Once this is called, the form is no longer capable of functioning, but all data should be retained.
     */
    public void seal() {
        triggerables = null;
        triggerIndex = null;
        conditionRepeatTargetIndex = null;
        //We may need ths one, actually
        exprEvalContext = null;
    }

    /**
     * Register a handler which is capable of handling send actions.
     */
    public void setSendCalloutHandler(FormSendCalloutHandler sendCalloutHandler) {
        this.sendCalloutHandler = sendCalloutHandler;
    }

    public String dispatchSendCallout(String url, Map<String, String> paramMap) {
        if (sendCalloutHandler == null) {
            return null;
        } else {
            return sendCalloutHandler.performHttpCalloutForResponse(url, paramMap);
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
CPD Civic Design
West End Commission set up to establish a blueprint for the future success of London's busiest area
Experts drawn from the worlds of business, academia, entertainment, and transport met for the first time on Wednesday 1 August 2012 as members of the newly-formed West End Commission, set up to establish a blueprint for the future success of London's busiest area.
Ten members of the West End Commission's 12-strong team gathered for its inaugural meeting at London's newly-reopened Hippodrome Casino. The team is headed by Manchester City Council's Chief Executive, Sir Howard Bernstein, and amongst the members of the team is Professor Yvonne Rydin, Chair of Planning Environment and Public Policy at the Bartlett School of Planning.
Sir Howard Bernstein is widely credited with overseeing the rebirth of Manchester following the IRA bombing of the city centre in 1996. The Manchester City Council chief executive has gone on to oversee a raft of major projects bringing millions of pounds into Manchester. Sir Howard said: "Today's meeting brings together for the first time the team of West End Commissioners, all of whom are renowned in their fields 1and this underlines both their independence and unique expertise they bring to the challenges and issues facing the West End.
Other members of the team attending the inaugural meeting were: Matthew Bennett of the Soho Society; Julian Bird, Chief Executive of the Society of London Theatre; Geoffrey Riesel, Chairman of the Radio Taxis Group, Greg Clark, international advisor on city investment and management; Harvey Goldsmith, performing arts promoter; Simon Thomas, Chairman of Hippodrome Casino Ltd; David Shaw, head of Regent Street at Crown Estate; Jim Steer, founder of Greengauge21 and the transport consultancy Steer Davies Gleave.
The West End Commission was created in January 2012 by Westminster City Council's cabinet and has the task of bringing together a range of independent experts to guide the future success of the West End and consider the challenges it faces. It will look into issues including transport, infrastructure, city management, safety and the promotion of business and visitor needs. It will also look at lessons from other cities both in the UK and abroad. The West End commission's first action today was to call for evidence from businesses, public sector organisations, the creative industries, the public and the voluntary sectors on the problems and priorities ahead for the West End. It will hold regular evidence sessions, starting in October, at which those with an interest in how the West End is run will be invited to put their views.
The new website for the West End Commission, www.westendcommission.com will allow users to submit written evidence to the Commission as well as updating on WEC news.

redpajama_set_name: RedPajamaCommonCrawl


text:
Unit Teaching the Holocaust and Armenian Genocide: For California Educators
You're exploring:
Lesson 14 Laws and the National Community
Lesson 1 Introducing the Unit
Lesson 2 Exploring Identity
Lesson 3 Stereotypes and "Single Stories"
Lesson 4 Universe of Obligation
Assessment Introducing and Dissecting the Writing Prompt
Lesson 5 The Roots and Impact of Antisemitism
Lesson 6 The Rise of Nationalism and the Collapse of the Ottoman Empire
Lesson 7 Genocide under the Cover of War
Assessment Introducing Evidence Logs
Lesson 8 Nationalism and the Aftermath of World War I
Lesson 9 The Weimar Republic
Assessment Adding to Evidence Logs, 1 of 4
Lesson 10 The Rise of the Nazi Party
Lesson 11 European Jewish Life before World War II
Lesson 12 Dismantling Democracy
Lesson 13 Do You Take the Oath?
Lesson 15 Power of Propaganda
Lesson 16 Youth and the National Community
Lesson 17 Kristallnacht
Lesson 18 Responding to a Refugee Crisis
Lesson 19 Race and Space
Lesson 20 The Holocaust: Bearing Witness
Lesson 21 The Holocaust: Range of Responses
Lesson 22 Justice and Judgement after the Holocaust
Lesson 23 Confronting Genocide Denial
Lesson 24 Survivor Testimony and the Legacy of Memory
Lesson 25 Choosing to Participate
Assessment Refining the Thesis and Finalizing Evidence Logs
Laws and the National Community
Students are introduced to the Nazis' idea of a "national community" and examine how the Nazis used the Nuremberg Laws to define who belonged.
One 50-min class period
Human & Civil Rights
About This Lesson
In the previous lesson, students analyzed some of the dilemmas experienced by individual Germans during the National Socialist revolution in Germany. In this lesson, students will continue this unit's historical case study by turning their attention to what happened after the revolution was complete and the Nazis firmly established control over Germany. Specifically, students will be introduced to the Nazis' idea of a "national community" shaped according to their racial ideals, a concept students will continue to explore in two lessons that follow this one. While there were many ways in which the Nazis shaped and cultivated their ideal "national community," in this unit students will look closely at three of those methods. In this lesson, they will examine the way the Nazis used laws to define who belonged to the "national community" and then separate those who did not belong. In future lessons, students will look at the Nazis' use of propaganda and their creation of youth groups to shape German society.
How can learning about the choices people made during past episodes of injustice, mass violence, or genocide help guide our choices today?
Guiding Questions
What are the consequences when governments use laws to create "in" groups and "out" groups in a society?
How do laws affect the ways that individuals think about their own identities and the identities of others? How do laws affect the relationships between individuals in a society?
Through a close reading and discussion of the Nuremberg Laws, students will examine how the Nazis sought to create a racially pure "national community," one that stripped Jews of their citizenship rights and narrowed Germany's universe of obligation.
By reflecting on a story of how the Nuremberg Laws affected one family, students will think more broadly about the power and limitations of laws to shape society and influence individual behavior.
This lesson is designed to fit into one 50-minute class period and includes:
2 teaching strategies
1 readings, available in English and in Spanish
3 handouts , available in English and in Spanish
1 assessment
Additional Context & Background
By 1934, Germany was firmly under Nazi control. After President von Hindenburg's death in August of that year, Adolf Hitler declared himself not only the nation's chancellor but also its Führer. The revolution was over, he told his closest associates. It was now time to consolidate power and normalize life in the "new Germany" they had created. They were determined to create a Volksgemeinschaft—a "national community" or, literally, a "people's community."
The term had become popular during World War I as a way of rallying support for the conflict. At that time, it simply meant that all Germans, regardless of class, religious, and social differences, would work together to achieve a national purpose—winning the war. But the Nazis interpreted its meaning differently. They used the word to advance the idea of a racially pure and harmonious national community united in its devotion to the German people, their nation, and their leader. In the words of a popular Nazi slogan, the goal was "Ein Volk! Ein Reich! Ein Führer!" ("One People! One Empire! One Leader!")
In his book Mein Kampf (My Struggle), Hitler described the foundation he sought for the national community, a foundation based on false myths about race:
Everything we admire on this earth today—science and art, technology and inventions—is only the creative product of a few peoples and originally perhaps one race [the "Aryans"]. On them depends the existence of this whole culture. If they perish, the beauty of this earth will sink into the grave with them.
In their effort to reshape the "national community" according to their racial ideals, the Nazis enacted hundreds of laws, policies, and decrees, including those that financially rewarded so-called Aryan couples for having children and those that allowed for the sterilization of people they considered "defective" or of supposedly inferior races.
Nearly 1,500 of the Nazis' laws, policies, and decrees enacted between 1933 and 1939 were designed to remove Jews from the country's political, economic, and cultural life. Among the most significant of these were the Nuremberg Laws. This set of laws included the Reich Citizenship Law and the Law for the Protection of German Blood and Honor, both announced at the Nuremberg Party Rally on September 15, 1935. The former stripped Jews of their rights to citizenship, including the rights to vote and hold a German passport. The latter unleashed a series of restrictions on the lives of German Jews, including the prohibition of sexual relationships between Jews and non-Jews as well as the forbiddance for Jews of flying the Reich flag.
These two laws raised an important question: What determined who was and who was not a Jew? According to many Jewish teachings, an individual was defined as a Jew if he or she was born to a Jewish mother or formally converted to Judaism. If a Jew converted to Christianity, he or she was no longer considered Jewish by many Jews. The Nazis did not accept that definition. They regarded Jews as members of neither a religious group nor an ethnic group (defined by their cultural heritage). Instead, they regarded Jews as members of a separate and inferior "race." Since, according to Nazi logic, "race" was not altered by conversion, people who were born Jewish would always be Jews, regardless of their religious beliefs or practices.
In reality, whether someone was German or Jewish could not be determined by medical or scientific tests. The question of defining German and Jewish identity was further complicated by the fact that there had been a great deal of intermarriage between the two groups, and there were thousands of people of mixed Jewish and non-Jewish ancestry, known to the Nazis as Mischlinge ("half-breeds" or "mixed-blood").
Responding to these questions, the Nazi government created precise legal definitions of who was a German and who was a Jew through an additional decree called the First Regulation to the Reich Citizenship Law, announced on November 14, 1935. (Debates about how to classify Mischlinge went on for years and were never completely resolved.) The detailed definitions the Nazis created are included in the resources in this lesson.
The Nuremberg Laws turned Jews from German citizens into "residents of Germany." The laws transformed the lives of Jews all over Germany, including thousands of people who had not previously known that their families had Jewish heritage. These laws placed Jews squarely outside of Germany's "universe of obligation."
Before you teach this lesson, please review the following guidance to tailor this lesson to your students' contexts and needs.
Connotation of the Term "National Community"
The German word for "national community," Volksgemeinschaft, implies a specific kind of community that the Nazis aspired to foster and has a meaning that is more specific in connotation than the English common-noun translation signifies. For this reason, we chose to include quotation marks around the English translation of this term to highlight this distinction. (Review the Context section for more information on the meaning of this term.)
Preparing Students for a Big Paper Activity
Activity 3 below uses the Big Paper teaching strategy, which we encourage you to familiarize yourself with before teaching the lesson. Note that in order for students to have a totally silent conversation with the text and with each other, you must provide very clear and explicit instructions for students prior to the start of the activity and answer any questions in advance. To get a sense of the final product for a Big Paper activity, refer to this Big Paper example on Facing History's website.
Big Paper: Building a Silent Conversation
Big Paper Example
Previewing Vocabulary
The following are key vocabulary terms used in this lesson:
"National community"
Add these words to your Word Wall, if you are using one for this unit, and provide necessary support to help students learn these words as you teach the lesson.
Word Wall
The Unit Essay Assessment
If your students are writing the final essay assessment for this unit, after teaching this lesson, instruct students to add evidence from the last five lessons to their evidence logs. For suggested activities and resources, see Adding to Evidence Logs, 2 of 4.
Adding to Evidence Logs, 2 of 4
Briefly Introduce the Nazi Concept of "National Community"
Open by telling students that in this lesson, and the two following lessons, they are going to examine closely the "national community" that the Nazis envisioned for Germany and the ways in which they tried to create it in the 1930s. To illustrate for students the importance of the concept of "national community" to the Nazis, you might tell them that the Nazis had a specific word for this special community: Volksgemeinschaft. Tell students that defining who belongs in the Nazis' idea of a "national community" is similar to defining who belongs in their universe of obligation.
Reflect on Responding to Injustice in Our Own Lives
Now, before looking at laws enacted by the Nazis, ask students to reflect on unfair laws or rules that they have experienced or witnessed in their own lives. Use the following journal prompt:
How do laws help to define a nation's universe of obligation? Can you think of an example of a current or past law that excludes people from your country's universe of obligation? Explain your example.
Students can share and discuss their thinking in a brief Think, Pair, Share activity.
Think, Pair, Share
Analyze Laws Used to Shape the National Community
Tell students that there are a variety of measures a government can take to shape society—and a variety of ways a government can exclude those who leaders consider to be outsiders from enjoying the benefits of belonging to the nation. Laws were one powerful tool the Nazis used for these purposes; between 1933 and 1939 they enacted nearly 1,500 laws, policies, and decrees that privileged "Aryans" and excluded, discriminated against, and persecuted Jews and other supposedly inferior groups.
In this activity, students will examine a set of laws known as the Nuremberg Laws using the Big Paper silent discussion strategy. (For classes with additional time, an extension to this lesson analyzes a variety of additional laws enacted by the Nazis.)
Divide the class into groups of three or four, and prepare a piece of chart paper for each group with one of the following handouts taped in the middle:
First Regulation to the Reich Citizenship Law
Law for the Protection of German Blood and Honor, Part 1
Make sure that each student has a pen or marker to write with, and then give them eight minutes to have a written discussion about their assigned handout in complete silence. The following questions can help guide their discussion:
What is the purpose of this law?
Who benefits from it and who is harmed by it?
What does the law suggest about who is included in Germany's "national community"?
How does the law define Germany's universe of obligation?
The written conversation should start with students' responses to these questions, but it can continue wherever the students take it. Students should feel free to annotate the text. If someone in the group writes a question, another member of the group should answer it. Students can draw lines connecting a comment to a particular question. Make sure students know that more than one of them can write on the Big Paper at the same time.
After the ten minutes, rotate each group to a different "big paper," and give them two or three minutes to read the document and the written conversation on that paper. They can add new comments and questions if they have them. Then rotate the groups one more time, making sure that each group has seen each of the three handouts at least once.
Finally, debrief the activity with the class, asking the following questions as checks for understanding:
How would you summarize the purpose of the Nuremberg Laws?
How did the laws you read and discussed contribute to creating the type of "national community" that the Nazis desired?
How might these laws have influenced the attitudes and actions of the German people? How might their lives and beliefs have changed as a result of these laws?
Examine the Impact of the Nuremberg Laws
Tell students that they will now read a personal account of how one family was affected by the enactment of the Nuremberg Laws. Instruct students that as you read aloud from the reading Discovering Jewish Blood, they should underline any information that helps them answer the following question:
How did the enactment of the Nuremberg Laws affect the lives of Marianne Schweitzer and her family?
After you finish reading, discuss with students their annotations as well as the effects of the Nuremberg Laws on the Schweitzer family using the Think, Pair, Share strategy.
End the lesson by giving students a few minutes to respond in their journals to one or more of the questions below. If necessary, they can complete their reflections for homework:
How did the Nuremberg Laws affect Marianne Schweitzer and her family members' status in German society? How did the laws influence how they thought about their own identities?
How might discriminatory laws influence the way we think about others in our society? About ourselves?
What other examples can you think of from history, literature, or your own life of laws or rules affecting how people think about and treat others? Of laws and rules affecting how people think about themselves?
What can be done to change laws that you disagree with? What would be required to change laws in your community (local, state, or national)? Which of these options, if any, were available to people in Germany in the 1930s?
Discovering Jewish Blood
Check for Understanding
The Big Paper activity provides a visual representation of students' thinking throughout the lesson that you can use to evaluate their understanding of the relationship between discriminatory laws and the way Germans thought about and treated each other.
Assign students to respond to one of the prompts at the end of the lesson on notecards instead of in their journals, so that you can collect the responses. Evaluate their responses to gain insight into students' understanding of the power of laws to shape society and individual behavior. Connections students are able to make to other examples from history, literature, or current events can provide evidence of a deeper level of understanding.
Extension Activities 1
View and Discuss A Class Divided
The film A Class Divided (60:00) tells the story of teacher Jane Elliott's third-grade classroom experiment, in which she temporarily separated her students by eye color. The results of her experiment provide powerful insight into how rules and laws created by authority figures can impact how we view our own identities and those of others. After viewing the film, ask students how the results of Elliott's classroom experiment might provide insight into the impact of the Nuremberg Laws (and other regulations enacted by the Nazis) on families such as the Schweitzers. The Connect, Extend, Challenge teaching strategy can help you structure the discussion.
A Class Divided
Connect, Extend, Challenge
Extension Activity 2
Delve More Deeply into the Concept of "National Community"
Share the reading The Common Interest before Self-Interest with students. It is short enough that you might simply project it for the class to read together. Ask students to take turns reading aloud each of the questions and answers on the pamphlet.
Lead a brief discussion with the class that focuses on the following questions:
How does this pamphlet define what it means to be German?
What does the phrase "racial comrade" suggest about the way Goebbels defined "Germanness"?
What did National Socialism offer to these "honestly creative" Germans? What did it ask of them?
The Common Interest before Self-Interest
Examine Additional Laws Designed to Shape the "National Community"
The readings Breeding the New German "Race" and A Wave of Discrimination provide additional important examples of laws enacted by the Nazis to shape their ideal "national community" of Aryans. These laws include dozens of discriminatory measures passed by national, state, regional, and local governments to exclude Jews from even the seemingly mundane aspects of German society, as well as laws that put into place national programs to encourage so-called Aryans to reproduce and to prevent non-Aryans from doing so. Consider sharing these readings with students and discussing the following questions:
How do these laws contribute to creating the type of "national community" that the Nazis desired?
How can laws affect the relationship between individuals and society? How do they affect the relationships individuals have with each other?
Breeding the New German "Race"
A Wave of Discrimination
These are the handouts, available in English and Spanish, that students use throughout the Laws and the National Community lesson plan.
Download the Files
First Regulation to the Reich Citizenship Law - PDF
First Regulation to the Reich Citizenship Law (en español) - PDF
Law for the Protection of German Blood and Honor, Part 1 - PDF
Law for the Protection of German Blood and Honor, Part 1 (en español) - PDF
Law for the Protection of German Blood and Honor, Part Two (en español) - PDF
Get Files Via Google
First Regulation to the Reich Citizenship Law (En Español)
Law for the Protection of German Blood and Honor, Part 1 (En Español)
These are the readings, videos, and images, available in English and Spanish, that students use throughout the Laws and the National Community lesson plan.
Find out how one family's lives changed when Hitler passed the Nuremberg Laws in Nazi Germany.
Do You Take the Oath?
Students consider the choices and reasoning of individual Germans who stayed quiet or spoke up during the first few years of Nazi rule.
Students consider how what they've learned about the rise of the Nazi Party influences their thinking about the essay prompt and practice making inferences.
Most teachers are willing to tackle the difficult topics, but we need the tools.
— Gabriela Calderon-Espinal, Bay Shore, NY


Approximately 300 athletes were in attendance for the first Academic Elite Session of the summer. We asked a handful of the campers what their experience has been like thus far.
How has your experience been at camp?
What's the best thing you have learned so far at camp?
How is this camp different from tournaments you have played in before?
What's the biggest thing you need to work on moving forward?


text:
Q: Intro Circuits Class Inductor question This is a question from my intro circuits class that I can't figure out the answer to:

Of course it's very simple, but I had a professor who was incomprehensible most of the time, and my textbook doesn't have any examples similar to this. Would someone please either point me in the right direction to answer this or suggest a good and free resource for me to use to teach myself?

A: Since this is homework, I won't solve this completely for you, but I'll show you how to set up the equations:
First question "a". Let's name the bottom node "ground", and the top node "node 1", and call its voltage "v1". Now for each of the elements you can write a branch equation:
\$\dfrac{\mathrm{d}i_1}{\mathrm{d}t} = -\dfrac{v_1(t)}{3H}\$ (\$i_1\$ directed opposite of passive reference convention)
\$\dfrac{\mathrm{d}i_2}{\mathrm{d}t} = \dfrac{v_1(t)}{6H}\$
\$i_R(t) = \dfrac{v_1(t)}{2\Omega}\$
You also have a node equation for node 1:
\$i_1(t) = i_2(t) + i_R(t)\$
Given the initial conditions, you can also work out that the resistor current at t=0 is -1 A, and so \$v_1(0) = -1A \cdot 2 \Omega = -2V\$
From here you should be able to work out a solution for the different currents over time. Since you only have one storage element (the two inductors in parallel are equivalent to a single inductor with 6*3/(6+3) = 2 H inductance), you'll most likely end up with v1(t) decaying exponentially, and then being able to work out the individual inductor currents from there.
For equation (b), follow the same method: write all the independent branch and node equations you can, then combine and simplify until you have a solvable set of equations.

A: Since The Photon has covered the 1st problem, I'll chime in with a hint on the 2nd problem:  the current source should not be a factor in your calculation of the inductor current, i.e., the inductor current is unaffected by the current source.

redpajama_set_name: RedPajamaStackExchange


With a stay at Aso Villa Park Hotel & Spa Resort in Aso, you'll be within a 15-minute drive of Cuddly Dominion and Aso Shrine. This hotel is 9.9 mi (15.9 km) from Mount Aso and 9.9 mi (15.9 km) from Mount Aso.
Make yourself at home in one of the 246 air-conditioned rooms featuring refrigerators. Complimentary wireless Internet access keeps you connected, and digital programming is available for your entertainment. Private bathrooms with shower/tub combinations feature complimentary toiletries and hair dryers. Conveniences include phones, as well as safes and coffee/tea makers.
Don't miss out on the many recreational opportunities, including hot springs, an indoor pool, and a spa tub. Additional features at this hotel include complimentary wireless Internet access, concierge services, and a banquet hall.
Enjoy Japanese cuisine at Papillon, one of the hotel's many dining establishments, which include 4 restaurants and a coffee shop/café. Quench your thirst with your favorite drink at the bar/lounge. Buffet breakfasts are available daily from 7 AM to 9:30 AM for a fee.
Reservations are required for private bath/onsen. Reservations can be made by contacting the hotel prior to arrival, using the contact information on the booking confirmation.
A tax is imposed by the city: JPY 150 per person, per night. This tax does not apply to children under 13 years of age.