text:
#include "core/animation/css/CSSAnimations.h"

#include "core/StylePropertyShorthand.h"
#include "core/animation/Animation.h"
#include "core/animation/CompositorAnimations.h"
#include "core/animation/DocumentTimeline.h"
#include "core/animation/ElementAnimations.h"
#include "core/animation/InertEffect.h"
#include "core/animation/Interpolation.h"
#include "core/animation/KeyframeEffectModel.h"
#include "core/animation/LegacyStyleInterpolation.h"
#include "core/animation/css/CSSAnimatableValueFactory.h"
#include "core/css/CSSKeyframeRule.h"
#include "core/css/CSSPropertyEquality.h"
#include "core/css/CSSPropertyMetadata.h"
#include "core/css/CSSValueList.h"
#include "core/css/resolver/CSSToStyleMap.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Element.h"
#include "core/dom/PseudoElement.h"
#include "core/dom/StyleEngine.h"
#include "core/events/AnimationEvent.h"
#include "core/events/TransitionEvent.h"
#include "core/frame/UseCounter.h"
#include "core/layout/LayoutObject.h"
#include "core/paint/PaintLayer.h"
#include "platform/Histogram.h"
#include "platform/animation/TimingFunction.h"
#include "public/platform/Platform.h"
#include "wtf/HashSet.h"
#include <algorithm>
#include <bitset>

namespace blink {

using PropertySet = HashSet<CSSPropertyID>;

namespace {

static StringKeyframeEffectModel* createKeyframeEffectModel(StyleResolver* resolver, const Element* animatingElement, Element& element, const ComputedStyle* style, const ComputedStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction, size_t animationIndex)
{
    // When the animating element is null, use its parent for scoping purposes.
    const Element* elementForScoping = animatingElement ? animatingElement : &element;
    const StyleRuleKeyframes* keyframesRule = resolver->findKeyframesRule(elementForScoping, name);
    ASSERT(keyframesRule);

    StringKeyframeVector keyframes;
    const HeapVector<Member<StyleRuleKeyframe>>& styleKeyframes = keyframesRule->keyframes();

    // Construct and populate the style for each keyframe
    PropertySet specifiedPropertiesForUseCounter;
    for (size_t i = 0; i < styleKeyframes.size(); ++i) {
        const StyleRuleKeyframe* styleKeyframe = styleKeyframes[i].get();
        RefPtr<StringKeyframe> keyframe = StringKeyframe::create();
        const Vector<double>& offsets = styleKeyframe->keys();
        ASSERT(!offsets.isEmpty());
        keyframe->setOffset(offsets[0]);
        keyframe->setEasing(defaultTimingFunction);
        const StylePropertySet& properties = styleKeyframe->properties();
        for (unsigned j = 0; j < properties.propertyCount(); j++) {
            CSSPropertyID property = properties.propertyAt(j).id();
            specifiedPropertiesForUseCounter.add(property);
            if (property == CSSPropertyAnimationTimingFunction) {
                const CSSValue& value = properties.propertyAt(j).value();
                RefPtr<TimingFunction> timingFunction;
                if (value.isInheritedValue() && parentStyle->animations()) {
                    timingFunction = parentStyle->animations()->timingFunctionList()[0];
                } else if (value.isValueList()) {
                    timingFunction = CSSToStyleMap::mapAnimationTimingFunction(toCSSValueList(value).item(0));
                } else {
                    DCHECK(value.isCSSWideKeyword());
                    timingFunction = CSSTimingData::initialTimingFunction();
                }
                keyframe->setEasing(timingFunction.release());
            } else if (CSSAnimations::isAnimatableProperty(property)) {
                keyframe->setCSSPropertyValue(property, properties.propertyAt(j).value());
            }
        }
        keyframes.append(keyframe);
        // The last keyframe specified at a given offset is used.
        for (size_t j = 1; j < offsets.size(); ++j) {
            keyframes.append(toStringKeyframe(keyframe->cloneWithOffset(offsets[j]).get()));
        }
    }

    DEFINE_STATIC_LOCAL(SparseHistogram, propertyHistogram, ("WebCore.Animation.CSSProperties"));
    for (CSSPropertyID property : specifiedPropertiesForUseCounter) {
        ASSERT(property != CSSPropertyInvalid);
        propertyHistogram.sample(UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(property));
    }

    // Merge duplicate keyframes.
    std::stable_sort(keyframes.begin(), keyframes.end(), Keyframe::compareOffsets);
    size_t targetIndex = 0;
    for (size_t i = 1; i < keyframes.size(); i++) {
        if (keyframes[i]->offset() == keyframes[targetIndex]->offset()) {
            for (const auto& property : keyframes[i]->properties())
                keyframes[targetIndex]->setCSSPropertyValue(property.cssProperty(), keyframes[i]->cssPropertyValue(property.cssProperty()));
        } else {
            targetIndex++;
            keyframes[targetIndex] = keyframes[i];
        }
    }
    if (!keyframes.isEmpty())
        keyframes.shrink(targetIndex + 1);

    // Add 0% and 100% keyframes if absent.
    RefPtr<StringKeyframe> startKeyframe = keyframes.isEmpty() ? nullptr : keyframes[0];
    if (!startKeyframe || keyframes[0]->offset() != 0) {
        startKeyframe = StringKeyframe::create();
        startKeyframe->setOffset(0);
        startKeyframe->setEasing(defaultTimingFunction);
        keyframes.prepend(startKeyframe);
    }
    RefPtr<StringKeyframe> endKeyframe = keyframes[keyframes.size() - 1];
    if (endKeyframe->offset() != 1) {
        endKeyframe = StringKeyframe::create();
        endKeyframe->setOffset(1);
        endKeyframe->setEasing(defaultTimingFunction);
        keyframes.append(endKeyframe);
    }
    ASSERT(keyframes.size() >= 2);
    ASSERT(!keyframes.first()->offset());
    ASSERT(keyframes.last()->offset() == 1);

    // FIXME: This is only used for use counting neutral keyframes running on the compositor.
    PropertySet allProperties;
    for (const auto& keyframe : keyframes) {
        for (const auto& property : keyframe->properties())
            allProperties.add(property.cssProperty());
    }
    const PropertyHandleSet& startKeyframeProperties = startKeyframe->properties();
    const PropertyHandleSet& endKeyframeProperties = endKeyframe->properties();
    bool missingStartValues = startKeyframeProperties.size() < allProperties.size();
    bool missingEndValues = endKeyframeProperties.size() < allProperties.size();
    if (missingStartValues || missingEndValues) {
        for (CSSPropertyID property : allProperties) {
            bool startNeedsValue = missingStartValues && !startKeyframeProperties.contains(PropertyHandle(property));
            bool endNeedsValue = missingEndValues && !endKeyframeProperties.contains(PropertyHandle(property));
            if (!startNeedsValue && !endNeedsValue)
                continue;
            if (CompositorAnimations::isCompositableProperty(property))
                UseCounter::count(elementForScoping->document(), UseCounter::SyntheticKeyframesInCompositedCSSAnimation);
        }
    }

    StringKeyframeEffectModel* model = StringKeyframeEffectModel::create(keyframes, &keyframes[0]->easing());
    if (animationIndex > 0 && model->hasSyntheticKeyframes())
        UseCounter::count(elementForScoping->document(), UseCounter::CSSAnimationsStackedNeutralKeyframe);
    return model;
}

} // namespace

CSSAnimations::CSSAnimations()
{
}

bool CSSAnimations::isAnimationForInspector(const Animation& animation)
{
    for (const auto& runningAnimation : m_runningAnimations) {
        if (runningAnimation->animation->sequenceNumber() == animation.sequenceNumber())
            return true;
    }
    return false;
}

bool CSSAnimations::isTransitionAnimationForInspector(const Animation& animation) const
{
    for (const auto& it : m_transitions) {
        if (it.value.animation->sequenceNumber() == animation.sequenceNumber())
            return true;
    }
    return false;
}

void CSSAnimations::calculateUpdate(const Element* animatingElement, Element& element, const ComputedStyle& style, ComputedStyle* parentStyle, CSSAnimationUpdate& animationUpdate, StyleResolver* resolver)
{
    calculateCompositorAnimationUpdate(animationUpdate, animatingElement, element, style, parentStyle);
    calculateAnimationUpdate(animationUpdate, animatingElement, element, style, parentStyle, resolver);
    calculateAnimationActiveInterpolations(animationUpdate, animatingElement);
    calculateTransitionUpdate(animationUpdate, animatingElement, style);
    calculateTransitionActiveInterpolations(animationUpdate, animatingElement);
}

static const KeyframeEffectModelBase* getKeyframeEffectModelBase(const AnimationEffect* effect)
{
    if (!effect)
        return nullptr;
    const EffectModel* model = nullptr;
    if (effect->isKeyframeEffect())
        model = toKeyframeEffect(effect)->model();
    else if (effect->isInertEffect())
        model = toInertEffect(effect)->model();
    if (!model || !model->isKeyframeEffectModel())
        return nullptr;
    return toKeyframeEffectModelBase(model);
}

void CSSAnimations::calculateCompositorAnimationUpdate(CSSAnimationUpdate& update, const Element* animatingElement, Element& element, const ComputedStyle& style, const ComputedStyle* parentStyle)
{
    ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr;

    // We only update compositor animations in response to changes in the base style.
    if (!elementAnimations || elementAnimations->isAnimationStyleChange())
        return;

    if (!animatingElement->layoutObject() || !animatingElement->layoutObject()->style())
        return;

    const ComputedStyle& oldStyle = *animatingElement->layoutObject()->style();
    if (!oldStyle.shouldCompositeForCurrentAnimations())
        return;

    bool transformZoomChanged = oldStyle.hasCurrentTransformAnimation() && oldStyle.effectiveZoom() != style.effectiveZoom();
    for (auto& entry : elementAnimations->animations()) {
        Animation& animation = *entry.key;
        const KeyframeEffectModelBase* keyframeEffect = getKeyframeEffectModelBase(animation.effect());
        if (!keyframeEffect)
            continue;

        bool updateCompositorKeyframes = false;
        if (transformZoomChanged && keyframeEffect->affects(PropertyHandle(CSSPropertyTransform))
            && keyframeEffect->snapshotAllCompositorKeyframes(element, style, parentStyle)) {
            updateCompositorKeyframes = true;
        } else if (keyframeEffect->hasSyntheticKeyframes()
            && keyframeEffect->snapshotNeutralCompositorKeyframes(element, oldStyle, style, parentStyle)) {
            updateCompositorKeyframes = true;
        }

        if (updateCompositorKeyframes)
            update.updateCompositorKeyframes(&animation);
    }
}

void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate& update, const Element* animatingElement, Element& element, const ComputedStyle& style, ComputedStyle* parentStyle, StyleResolver* resolver)
{
    const ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr;

    bool isAnimationStyleChange = elementAnimations && elementAnimations->isAnimationStyleChange();

#if !ENABLE(ASSERT)
    // If we're in an animation style change, no animations can have started, been cancelled or changed play state.
    // When ASSERT is enabled, we verify this optimization.
    if (isAnimationStyleChange)
        return;
#endif

    const CSSAnimationData* animationData = style.animations();
    const CSSAnimations* cssAnimations = elementAnimations ? &elementAnimations->cssAnimations() : nullptr;
    const Element* elementForScoping = animatingElement ? animatingElement : &element;

    Vector<bool> cancelRunningAnimationFlags(cssAnimations ? cssAnimations->m_runningAnimations.size() : 0);
    for (bool& flag : cancelRunningAnimationFlags)
        flag = true;

    if (animationData && style.display() != NONE) {
        const Vector<AtomicString>& nameList = animationData->nameList();
        for (size_t i = 0; i < nameList.size(); ++i) {
            AtomicString name = nameList[i];
            if (name == CSSAnimationData::initialName())
                continue;

            // Find n where this is the nth occurence of this animation name.
            size_t nameIndex = 0;
            for (size_t j = 0; j < i; j++) {
                if (nameList[j] == name)
                    nameIndex++;
            }

            const bool isPaused = CSSTimingData::getRepeated(animationData->playStateList(), i) == AnimPlayStatePaused;

            Timing timing = animationData->convertToTiming(i);
            Timing specifiedTiming = timing;
            RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunction;
            timing.timingFunction = Timing::defaults().timingFunction;

            StyleRuleKeyframes* keyframesRule = resolver->findKeyframesRule(elementForScoping, name);
            if (!keyframesRule) {
                element.document().styleEngine().setHasUnresolvedKeyframesRule();
                continue; // Cancel the animation if there's no style rule for it.
            }

            const RunningAnimation* existingAnimation = nullptr;
            size_t existingAnimationIndex = 0;

            if (cssAnimations) {
                for (size_t i = 0; i < cssAnimations->m_runningAnimations.size(); i++) {
                    const RunningAnimation& runningAnimation = *cssAnimations->m_runningAnimations[i];
                    if (runningAnimation.name == name && runningAnimation.nameIndex == nameIndex) {
                        existingAnimation = &runningAnimation;
                        existingAnimationIndex = i;
                        break;
                    }
                }
            }

            if (existingAnimation) {
                cancelRunningAnimationFlags[existingAnimationIndex] = false;

                Animation* animation = existingAnimation->animation.get();

                if (keyframesRule != existingAnimation->styleRule || keyframesRule->version() != existingAnimation->styleRuleVersion || existingAnimation->specifiedTiming != specifiedTiming) {
                    ASSERT(!isAnimationStyleChange);
                    update.updateAnimation(existingAnimationIndex, animation, *InertEffect::create(
                        createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, name, keyframeTimingFunction.get(), i),
                        timing, isPaused, animation->unlimitedCurrentTimeInternal()), specifiedTiming, keyframesRule);
                }

                if (isPaused != animation->paused()) {
                    ASSERT(!isAnimationStyleChange);
                    update.toggleAnimationIndexPaused(existingAnimationIndex);
                }
            } else {
                ASSERT(!isAnimationStyleChange);
                update.startAnimation(name, nameIndex, *InertEffect::create(
                    createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, name, keyframeTimingFunction.get(), i),
                    timing, isPaused, 0), specifiedTiming, keyframesRule);
            }
        }
    }

    for (size_t i = 0; i < cancelRunningAnimationFlags.size(); i++) {
        if (cancelRunningAnimationFlags[i]) {
            ASSERT(cssAnimations && !isAnimationStyleChange);
            update.cancelAnimation(i, *cssAnimations->m_runningAnimations[i]->animation);
        }
    }
}

void CSSAnimations::snapshotCompositorKeyframes(Element& element, CSSAnimationUpdate& update, const ComputedStyle& style, const ComputedStyle* parentStyle)
{
    const auto& snapshot = [&element, &style, parentStyle](const AnimationEffect* effect)
    {
        const KeyframeEffectModelBase* keyframeEffect = getKeyframeEffectModelBase(effect);
        if (keyframeEffect && keyframeEffect->needsCompositorKeyframesSnapshot())
            keyframeEffect->snapshotAllCompositorKeyframes(element, style, parentStyle);
    };

    ElementAnimations* elementAnimations = element.elementAnimations();
    if (elementAnimations) {
        for (auto& entry : elementAnimations->animations())
            snapshot(entry.key->effect());
    }

    for (const auto& newAnimation : update.newAnimations())
        snapshot(newAnimation.effect.get());

    for (const auto& updatedAnimation : update.animationsWithUpdates())
        snapshot(updatedAnimation.effect.get());

    for (const auto& newTransition : update.newTransitions())
        snapshot(newTransition.value.effect.get());
}

void CSSAnimations::maybeApplyPendingUpdate(Element* element)
{
    m_previousActiveInterpolationsForAnimations.clear();
    if (m_pendingUpdate.isEmpty())
        return;

    m_previousActiveInterpolationsForAnimations.swap(m_pendingUpdate.activeInterpolationsForAnimations());

    // FIXME: cancelling, pausing, unpausing animations all query compositingState, which is not necessarily up to date here
    // since we call this from recalc style.
    // https://code.google.com/p/chromium/issues/detail?id=339847
    DisableCompositingQueryAsserts disabler;

    for (size_t pausedIndex : m_pendingUpdate.animationIndicesWithPauseToggled()) {
        Animation& animation = *m_runningAnimations[pausedIndex]->animation;
        if (animation.paused())
            animation.unpause();
        else
            animation.pause();
        if (animation.outdated())
            animation.update(TimingUpdateOnDemand);
    }

    for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes())
        animation->setCompositorPending(true);

    for (const auto& entry : m_pendingUpdate.animationsWithUpdates()) {
        KeyframeEffect* effect = toKeyframeEffect(entry.animation->effect());

        effect->setModel(entry.effect->model());
        effect->updateSpecifiedTiming(entry.effect->specifiedTiming());

        m_runningAnimations[entry.index]->update(entry);
    }

    const Vector<size_t>& cancelledIndices = m_pendingUpdate.cancelledAnimationIndices();
    for (size_t i = cancelledIndices.size(); i-- > 0;) {
        ASSERT(i == cancelledIndices.size() - 1 || cancelledIndices[i] < cancelledIndices[i + 1]);
        Animation& animation = *m_runningAnimations[cancelledIndices[i]]->animation;
        animation.cancel();
        animation.update(TimingUpdateOnDemand);
        m_runningAnimations.remove(cancelledIndices[i]);
    }

    for (const auto& entry : m_pendingUpdate.newAnimations()) {
        const InertEffect* inertAnimation = entry.effect.get();
        AnimationEventDelegate* eventDelegate = new AnimationEventDelegate(element, entry.name);
        KeyframeEffect* effect = KeyframeEffect::create(element, inertAnimation->model(), inertAnimation->specifiedTiming(), KeyframeEffect::DefaultPriority, eventDelegate);
        Animation* animation = element->document().timeline().play(effect);
        animation->setId(entry.name);
        if (inertAnimation->paused())
            animation->pause();
        animation->update(TimingUpdateOnDemand);

        m_runningAnimations.append(new RunningAnimation(animation, entry));
    }

    // Transitions that are run on the compositor only update main-thread state
    // lazily. However, we need the new state to know what the from state shoud
    // be when transitions are retargeted. Instead of triggering complete style
    // recalculation, we find these cases by searching for new transitions that
    // have matching cancelled animation property IDs on the compositor.
    HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffect>, double>> retargetedCompositorTransitions;
    for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) {
        ASSERT(m_transitions.contains(id));

        Animation* animation = m_transitions.take(id).animation;
        KeyframeEffect* effect = toKeyframeEffect(animation->effect());
        if (effect->hasActiveAnimationsOnCompositor(id) && m_pendingUpdate.newTransitions().find(id) != m_pendingUpdate.newTransitions().end() && !animation->limited())
            retargetedCompositorTransitions.add(id, std::pair<KeyframeEffect*, double>(effect, animation->startTimeInternal()));
        animation->cancel();
        // after cancelation, transitions must be downgraded or they'll fail
        // to be considered when retriggering themselves. This can happen if
        // the transition is captured through getAnimations then played.
        if (animation->effect() && animation->effect()->isKeyframeEffect())
            toKeyframeEffect(animation->effect())->downgradeToNormal();
        animation->update(TimingUpdateOnDemand);
    }

    for (CSSPropertyID id : m_pendingUpdate.finishedTransitions()) {
        // This transition can also be cancelled and finished at the same time
        if (m_transitions.contains(id)) {
            Animation* animation = m_transitions.take(id).animation;
            // Transition must be downgraded
            if (animation->effect() && animation->effect()->isKeyframeEffect())
                toKeyframeEffect(animation->effect())->downgradeToNormal();
        }
    }

    for (const auto& entry : m_pendingUpdate.newTransitions()) {
        const CSSAnimationUpdate::NewTransition& newTransition = entry.value;

        RunningTransition runningTransition;
        runningTransition.from = newTransition.from;
        runningTransition.to = newTransition.to;
        runningTransition.reversingAdjustedStartValue = newTransition.reversingAdjustedStartValue;
        runningTransition.reversingShorteningFactor = newTransition.reversingShorteningFactor;

        CSSPropertyID id = newTransition.id;
        const InertEffect* inertAnimation = newTransition.effect.get();
        TransitionEventDelegate* eventDelegate = new TransitionEventDelegate(element, id);

        EffectModel* model = inertAnimation->model();

        if (retargetedCompositorTransitions.contains(id)) {
            const std::pair<Member<KeyframeEffect>, double>& oldTransition = retargetedCompositorTransitions.get(id);
            KeyframeEffect* oldAnimation = oldTransition.first;
            double oldStartTime = oldTransition.second;
            double inheritedTime = isNull(oldStartTime) ? 0 : element->document().timeline().currentTimeInternal() - oldStartTime;

            AnimatableValueKeyframeEffectModel* oldEffect = toAnimatableValueKeyframeEffectModel(inertAnimation->model());
            const KeyframeVector& frames = oldEffect->getFrames();

            AnimatableValueKeyframeVector newFrames;
            newFrames.append(toAnimatableValueKeyframe(frames[0]->clone().get()));
            newFrames.append(toAnimatableValueKeyframe(frames[1]->clone().get()));
            newFrames.append(toAnimatableValueKeyframe(frames[2]->clone().get()));
            newFrames[0]->clearPropertyValue(id);
            newFrames[1]->clearPropertyValue(id);

            InertEffect* inertAnimationForSampling = InertEffect::create(oldAnimation->model(), oldAnimation->specifiedTiming(), false, inheritedTime);
            Vector<RefPtr<Interpolation>> sample;
            inertAnimationForSampling->sample(sample);
            if (sample.size() == 1) {
                newFrames[0]->setPropertyValue(id, toLegacyStyleInterpolation(sample.at(0).get())->currentValue());
                newFrames[1]->setPropertyValue(id, toLegacyStyleInterpolation(sample.at(0).get())->currentValue());
                model = AnimatableValueKeyframeEffectModel::create(newFrames);
            }
        }

        KeyframeEffect* transition = KeyframeEffect::create(element, model, inertAnimation->specifiedTiming(), KeyframeEffect::TransitionPriority, eventDelegate);
        Animation* animation = element->document().timeline().play(transition);
        animation->setId(getPropertyName(newTransition.id));
        // Set the current time as the start time for retargeted transitions
        if (retargetedCompositorTransitions.contains(id))
            animation->setStartTime(element->document().timeline().currentTime());
        animation->update(TimingUpdateOnDemand);
        runningTransition.animation = animation;
        m_transitions.set(id, runningTransition);
        ASSERT(id != CSSPropertyInvalid);

        DEFINE_STATIC_LOCAL(SparseHistogram, propertyHistogram, ("WebCore.Animation.CSSProperties"));
        propertyHistogram.sample(UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(id));
    }
    clearPendingUpdate();
}

void CSSAnimations::calculateTransitionUpdateForProperty(CSSPropertyID id, const CSSTransitionData& transitionData, size_t transitionIndex, const ComputedStyle& oldStyle, const ComputedStyle& style, const TransitionMap* activeTransitions, CSSAnimationUpdate& update, const Element* element)
{
    RefPtr<AnimatableValue> to = nullptr;
    const RunningTransition* interruptedTransition = nullptr;
    if (activeTransitions) {
        TransitionMap::const_iterator activeTransitionIter = activeTransitions->find(id);
        if (activeTransitionIter != activeTransitions->end()) {
            const RunningTransition* runningTransition = &activeTransitionIter->value;
            to = CSSAnimatableValueFactory::create(id, style);
            const AnimatableValue* activeTo = runningTransition->to;
            if (to->equals(activeTo))
                return;
            update.cancelTransition(id);
            ASSERT(!element->elementAnimations() || !element->elementAnimations()->isAnimationStyleChange());

            if (to->equals(runningTransition->reversingAdjustedStartValue.get()))
                interruptedTransition = runningTransition;
        }
    }

    if (CSSPropertyEquality::propertiesEqual(id, oldStyle, style))
        return;
    if (!to)
        to = CSSAnimatableValueFactory::create(id, style);

    RefPtr<AnimatableValue> from = CSSAnimatableValueFactory::create(id, oldStyle);
    // If we have multiple transitions on the same property, we will use the
    // last one since we iterate over them in order.
    if (AnimatableValue::usesDefaultInterpolation(to.get(), from.get()))
        return;

    Timing timing = transitionData.convertToTiming(transitionIndex);
    if (timing.startDelay + timing.iterationDuration <= 0)
        return;

    AnimatableValue* reversingAdjustedStartValue = from.get();
    double reversingShorteningFactor = 1;
    if (interruptedTransition) {
        const double interruptedProgress = interruptedTransition->animation->effect()->progress();
        if (!std::isnan(interruptedProgress)) {
            // const_cast because we need to take a ref later when passing to startTransition.
            reversingAdjustedStartValue = const_cast<AnimatableValue*>(interruptedTransition->to);
            reversingShorteningFactor = clampTo(
                (interruptedProgress * interruptedTransition->reversingShorteningFactor) +
                (1 - interruptedTransition->reversingShorteningFactor), 0.0, 1.0);
            timing.iterationDuration *= reversingShorteningFactor;
            if (timing.startDelay < 0) {
                timing.startDelay *= reversingShorteningFactor;
            }
        }
    }

    AnimatableValueKeyframeVector keyframes;
    double startKeyframeOffset = 0;

    if (timing.startDelay > 0) {
        timing.iterationDuration += timing.startDelay;
        startKeyframeOffset = timing.startDelay / timing.iterationDuration;
        timing.startDelay = 0;
    }

    RefPtr<AnimatableValueKeyframe> delayKeyframe = AnimatableValueKeyframe::create();
    delayKeyframe->setPropertyValue(id, from.get());
    delayKeyframe->setOffset(0);
    keyframes.append(delayKeyframe);

    RefPtr<AnimatableValueKeyframe> startKeyframe = AnimatableValueKeyframe::create();
    startKeyframe->setPropertyValue(id, from.get());
    startKeyframe->setOffset(startKeyframeOffset);
    startKeyframe->setEasing(timing.timingFunction.release());
    timing.timingFunction = LinearTimingFunction::shared();
    keyframes.append(startKeyframe);

    RefPtr<AnimatableValueKeyframe> endKeyframe = AnimatableValueKeyframe::create();
    endKeyframe->setPropertyValue(id, to.get());
    endKeyframe->setOffset(1);
    keyframes.append(endKeyframe);

    AnimatableValueKeyframeEffectModel* model = AnimatableValueKeyframeEffectModel::create(keyframes);
    update.startTransition(
        id, from.get(), to.get(), reversingAdjustedStartValue, reversingShorteningFactor,
        *InertEffect::create(model, timing, false, 0));
    ASSERT(!element->elementAnimations() || !element->elementAnimations()->isAnimationStyleChange());
}

void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, const Element* animatingElement, const ComputedStyle& style)
{
    if (!animatingElement)
        return;

    if (animatingElement->document().printing() || animatingElement->document().wasPrinting())
        return;

    ElementAnimations* elementAnimations = animatingElement->elementAnimations();
    const TransitionMap* activeTransitions = elementAnimations ? &elementAnimations->cssAnimations().m_transitions : nullptr;
    const CSSTransitionData* transitionData = style.transitions();

#if ENABLE(ASSERT)
    // In debug builds we verify that it would have been safe to avoid populating and testing listedProperties if the style recalc is due to animation.
    const bool animationStyleRecalc = false;
#else
    // In release builds we avoid the cost of checking for new and interrupted transitions if the style recalc is due to animation.
    const bool animationStyleRecalc = elementAnimations && elementAnimations->isAnimationStyleChange();
#endif

    std::bitset<numCSSProperties> listedProperties;
    bool anyTransitionHadTransitionAll = false;
    const LayoutObject* layoutObject = animatingElement->layoutObject();
    if (!animationStyleRecalc && style.display() != NONE && layoutObject && layoutObject->style() && transitionData) {
        const ComputedStyle& oldStyle = *layoutObject->style();

        for (size_t i = 0; i < transitionData->propertyList().size(); ++i) {
            const CSSTransitionData::TransitionProperty& transitionProperty = transitionData->propertyList()[i];
            if (transitionProperty.propertyType != CSSTransitionData::TransitionKnownProperty)
                continue;

            CSSPropertyID property = resolveCSSPropertyID(transitionProperty.unresolvedProperty);
            bool animateAll = property == CSSPropertyAll;
            if (animateAll)
                anyTransitionHadTransitionAll = true;
            const StylePropertyShorthand& propertyList = animateAll ? CSSAnimations::propertiesForTransitionAll() : shorthandForProperty(property);
            // If not a shorthand we only execute one iteration of this loop, and refer to the property directly.
            for (unsigned j = 0; !j || j < propertyList.length(); ++j) {
                CSSPropertyID id = propertyList.length() ? propertyList.properties()[j] : property;
                ASSERT(id >= firstCSSProperty);

                if (!animateAll) {
                    if (CSSPropertyMetadata::isInterpolableProperty(id))
                        listedProperties.set(id - firstCSSProperty);
                    else
                        continue;
                }

                // FIXME: We should transition if an !important property changes even when an animation is running,
                // but this is a bit hard to do with the current applyMatchedProperties system.
                PropertyHandle property = PropertyHandle(id);
                if (!update.activeInterpolationsForAnimations().contains(property)
                    && (!elementAnimations || !elementAnimations->cssAnimations().m_previousActiveInterpolationsForAnimations.contains(property))) {
                    calculateTransitionUpdateForProperty(id, *transitionData, i, oldStyle, style, activeTransitions, update, animatingElement);
                }
            }
        }
    }

    if (activeTransitions) {
        for (const auto& entry : *activeTransitions) {
            CSSPropertyID id = entry.key;
            if (!anyTransitionHadTransitionAll && !animationStyleRecalc && !listedProperties.test(id - firstCSSProperty)) {
                // TODO: Figure out why this fails on Chrome OS login page. crbug.com/365507
                // ASSERT(animation.playStateInternal() == Animation::Finished || !(elementAnimations && elementAnimations->isAnimationStyleChange()));
                update.cancelTransition(id);
            } else if (entry.value.animation->finishedInternal()) {
                update.finishTransition(id);
            }
        }
    }
}

void CSSAnimations::cancel()
{
    for (const auto& runningAnimation : m_runningAnimations) {
        runningAnimation->animation->cancel();
        runningAnimation->animation->update(TimingUpdateOnDemand);
    }

    for (const auto& entry : m_transitions) {
        entry.value.animation->cancel();
        entry.value.animation->update(TimingUpdateOnDemand);
    }

    m_runningAnimations.clear();
    m_transitions.clear();
    clearPendingUpdate();
}

static bool isStylePropertyHandle(const PropertyHandle& propertyHandle)
{
    return propertyHandle.isCSSProperty() || propertyHandle.isPresentationAttribute();
}

void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& update, const Element* animatingElement)
{
    ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr;
    AnimationStack* animationStack = elementAnimations ? &elementAnimations->animationStack() : nullptr;

    if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpty()) {
        ActiveInterpolationsMap activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, nullptr, nullptr, KeyframeEffect::DefaultPriority, isStylePropertyHandle));
        update.adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
        return;
    }

    HeapVector<Member<const InertEffect>> newEffects;
    for (const auto& newAnimation : update.newAnimations())
        newEffects.append(newAnimation.effect);
    for (const auto& updatedAnimation : update.animationsWithUpdates())
        newEffects.append(updatedAnimation.effect); // Animations with updates use a temporary InertEffect for the current frame.

    ActiveInterpolationsMap activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, &newEffects, &update.suppressedAnimations(), KeyframeEffect::DefaultPriority, isStylePropertyHandle));
    update.adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
}

void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate& update, const Element* animatingElement)
{
    ElementAnimations* elementAnimations = animatingElement ? animatingElement->elementAnimations() : nullptr;
    AnimationStack* animationStack = elementAnimations ? &elementAnimations->animationStack() : nullptr;

    ActiveInterpolationsMap activeInterpolationsForTransitions;
    if (update.newTransitions().isEmpty() && update.cancelledTransitions().isEmpty()) {
        activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, nullptr, nullptr, KeyframeEffect::TransitionPriority, isStylePropertyHandle);
    } else {
        HeapVector<Member<const InertEffect>> newTransitions;
        for (const auto& entry : update.newTransitions())
            newTransitions.append(entry.value.effect.get());

        HeapHashSet<Member<const Animation>> cancelledAnimations;
        if (!update.cancelledTransitions().isEmpty()) {
            ASSERT(elementAnimations);
            const TransitionMap& transitionMap = elementAnimations->cssAnimations().m_transitions;
            for (CSSPropertyID id : update.cancelledTransitions()) {
                ASSERT(transitionMap.contains(id));
                cancelledAnimations.add(transitionMap.get(id).animation.get());
            }
        }

        activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, &newTransitions, &cancelledAnimations, KeyframeEffect::TransitionPriority, isStylePropertyHandle);
    }

    // Properties being animated by animations don't get values from transitions applied.
    if (!update.activeInterpolationsForAnimations().isEmpty() && !activeInterpolationsForTransitions.isEmpty()) {
        for (const auto& entry : update.activeInterpolationsForAnimations())
            activeInterpolationsForTransitions.remove(entry.key);
    }
    update.adoptActiveInterpolationsForTransitions(activeInterpolationsForTransitions);
}

EventTarget* CSSAnimations::AnimationEventDelegate::eventTarget() const
{
    return EventPath::eventTargetRespectingTargetRules(*m_animationTarget);
}

void CSSAnimations::AnimationEventDelegate::maybeDispatch(Document::ListenerType listenerType, const AtomicString& eventName, double elapsedTime)
{
    if (m_animationTarget->document().hasListenerType(listenerType)) {
        AnimationEvent* event = AnimationEvent::create(eventName, m_name, elapsedTime);
        event->setTarget(eventTarget());
        document().enqueueAnimationFrameEvent(event);
    }
}

bool CSSAnimations::AnimationEventDelegate::requiresIterationEvents(const AnimationEffect& animationNode)
{
    return document().hasListenerType(Document::ANIMATIONITERATION_LISTENER);
}

void CSSAnimations::AnimationEventDelegate::onEventCondition(const AnimationEffect& animationNode)
{
    const AnimationEffect::Phase currentPhase = animationNode.getPhase();
    const double currentIteration = animationNode.currentIteration();

    if (m_previousPhase != currentPhase
        && (currentPhase == AnimationEffect::PhaseActive || currentPhase == AnimationEffect::PhaseAfter)
        && (m_previousPhase == AnimationEffect::PhaseNone || m_previousPhase == AnimationEffect::PhaseBefore)) {
        const double startDelay = animationNode.specifiedTiming().startDelay;
        const double elapsedTime = startDelay < 0 ? -startDelay : 0;
        maybeDispatch(Document::ANIMATIONSTART_LISTENER, EventTypeNames::animationstart, elapsedTime);
    }

    if (currentPhase == AnimationEffect::PhaseActive && m_previousPhase == currentPhase && m_previousIteration != currentIteration) {
        // We fire only a single event for all iterations thast terminate
        // between a single pair of samples. See http://crbug.com/275263. For
        // compatibility with the existing implementation, this event uses
        // the elapsedTime for the first iteration in question.
        ASSERT(!std::isnan(animationNode.specifiedTiming().iterationDuration));
        const double elapsedTime = animationNode.specifiedTiming().iterationDuration * (m_previousIteration + 1);
        maybeDispatch(Document::ANIMATIONITERATION_LISTENER, EventTypeNames::animationiteration, elapsedTime);
    }

    if (currentPhase == AnimationEffect::PhaseAfter && m_previousPhase != AnimationEffect::PhaseAfter)
        maybeDispatch(Document::ANIMATIONEND_LISTENER, EventTypeNames::animationend, animationNode.activeDurationInternal());

    m_previousPhase = currentPhase;
    m_previousIteration = currentIteration;
}

DEFINE_TRACE(CSSAnimations::AnimationEventDelegate)
{
    visitor->trace(m_animationTarget);
    AnimationEffect::EventDelegate::trace(visitor);
}

EventTarget* CSSAnimations::TransitionEventDelegate::eventTarget() const
{
    return EventPath::eventTargetRespectingTargetRules(*m_transitionTarget);
}

void CSSAnimations::TransitionEventDelegate::onEventCondition(const AnimationEffect& animationNode)
{
    const AnimationEffect::Phase currentPhase = animationNode.getPhase();
    if (currentPhase == AnimationEffect::PhaseAfter && currentPhase != m_previousPhase && document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
        String propertyName = getPropertyNameString(m_property);
        const Timing& timing = animationNode.specifiedTiming();
        double elapsedTime = timing.iterationDuration;
        const AtomicString& eventType = EventTypeNames::transitionend;
        String pseudoElement = PseudoElement::pseudoElementNameForEvents(getPseudoId());
        TransitionEvent* event = TransitionEvent::create(eventType, propertyName, elapsedTime, pseudoElement);
        event->setTarget(eventTarget());
        document().enqueueAnimationFrameEvent(event);
    }

    m_previousPhase = currentPhase;
}

DEFINE_TRACE(CSSAnimations::TransitionEventDelegate)
{
    visitor->trace(m_transitionTarget);
    AnimationEffect::EventDelegate::trace(visitor);
}

const StylePropertyShorthand& CSSAnimations::propertiesForTransitionAll()
{
    DEFINE_STATIC_LOCAL(Vector<CSSPropertyID>, properties, ());
    DEFINE_STATIC_LOCAL(StylePropertyShorthand, propertyShorthand, ());
    if (properties.isEmpty()) {
        for (int i = firstCSSProperty; i < lastCSSProperty; ++i) {
            CSSPropertyID id = convertToCSSPropertyID(i);
            // Avoid creating overlapping transitions with perspective-origin and transition-origin.
            if (id == CSSPropertyWebkitPerspectiveOriginX
                || id == CSSPropertyWebkitPerspectiveOriginY
                || id == CSSPropertyWebkitTransformOriginX
                || id == CSSPropertyWebkitTransformOriginY
                || id == CSSPropertyWebkitTransformOriginZ)
                continue;
            if (CSSPropertyMetadata::isInterpolableProperty(id))
                properties.append(id);
        }
        propertyShorthand = StylePropertyShorthand(CSSPropertyInvalid, properties.begin(), properties.size());
    }
    return propertyShorthand;
}

// Properties that affect animations are not allowed to be affected by animations.
// http://w3c.github.io/web-animations/#not-animatable-section
bool CSSAnimations::isAnimatableProperty(CSSPropertyID property)
{
    switch (property) {
    case CSSPropertyAnimation:
    case CSSPropertyAnimationDelay:
    case CSSPropertyAnimationDirection:
    case CSSPropertyAnimationDuration:
    case CSSPropertyAnimationFillMode:
    case CSSPropertyAnimationIterationCount:
    case CSSPropertyAnimationName:
    case CSSPropertyAnimationPlayState:
    case CSSPropertyAnimationTimingFunction:
    case CSSPropertyDisplay:
    case CSSPropertyTransition:
    case CSSPropertyTransitionDelay:
    case CSSPropertyTransitionDuration:
    case CSSPropertyTransitionProperty:
    case CSSPropertyTransitionTimingFunction:
        return false;
    default:
        return true;
    }
}

DEFINE_TRACE(CSSAnimations)
{
    visitor->trace(m_transitions);
    visitor->trace(m_pendingUpdate);
    visitor->trace(m_runningAnimations);
}

} // namespace blink


text:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';

import { UATModule } from './lib/UAT.module';

import { AppRoutingModule } from './app.routes';
import { AppComponent } from './app.component';
import { NavigationLink, MenuInput } from './menu-items/menu-items.components';
import { HomeComponent } from './home';
import { ColorViewerComponent } from './color-viewer';
import { ColorButtonComponent } from './color-button';
import { CollapsingMenuColorWidgetComponent } from './collapsing-menu-color-widget';
import { DropdownMenuColorWidgetComponent } from './dropdown-menu-color-widget';
import { FooComponent } from './home/foo.component';

import { UATDropdownInputServiceToken } from './lib/dropdown-input/dropdown-input.component';
import { DemoDropdownInputService } from './demo-dropdown-service/demo-dropdown-input.service';
import { DragAndDropComponent } from './drag-and-drop/drag-and-drop.component';

function dddisFactory() {
  return new DemoDropdownInputService();
}

@NgModule({
  declarations: [
    AppComponent,
	  NavigationLink,
	  MenuInput,
	  HomeComponent,
	  ColorViewerComponent,
	  ColorButtonComponent,
	  CollapsingMenuColorWidgetComponent,
    DropdownMenuColorWidgetComponent,
    FooComponent,
    DragAndDropComponent

  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
	  ReactiveFormsModule,
    HttpModule,
	  RouterModule,
	  AppRoutingModule,
    UATModule.forRoot(),
  ],
  providers: [
    { provide: UATDropdownInputServiceToken, useClass: DemoDropdownInputService}
  ],
  entryComponents: [
    NavigationLink,
    MenuInput,

  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

redpajama_set_name: RedPajamaGithub


text:
package cn.itcast.sh05.jbpm.pd;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipInputStream;

import javax.transaction.xa.XAException;

import org.jbpm.api.Configuration;
import org.jbpm.api.Deployment;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessEngine;
import org.junit.Test;

/**
 * Á÷³Ì¶¨Òå¹ÜÀí
 *    1¡¢¶ÔÁ÷³Ì¶¨Òå½øÐв¿Êð
 *    2¡¢¶ÔÁ÷³Ì¶¨Òå½øÐÐɾ³ý
 *    3¡¢¶ÔÁ÷³Ìͼ½øÐв鿴
 *    4¡¢¶ÔÁ÷³Ì¶¨Òå½øÐвéѯ
 * @author zd
 *
 */
public class PDManager {
	/**
	 * ¶ÔÁ÷³Ì¶¨Òå½øÐз¢²¼
	 */
	@Test
	public void testDeployFromClasspath(){
		/**
		 * »ñµÃjbpmµÄÁ÷³ÌÒýÇæ
		 */
		ProcessEngine processEngine = Configuration.getProcessEngine();
		/**
		 * ÏÂÒ»¸öapiµÄµ÷ÓÃÕßÊÇÉÏÒ»¸öapiµÄ·µ»ØÖµ£¬ËùÒÔ¿ÉÒÔÓÃÁ´Ê½±à³Ì
		 */
		processEngine.getRepositoryService()
		.createDeployment()
		.addResourceFromClasspath("qingjia.jpdl.xml")
		.addResourceFromClasspath("qingjia.png")
		.deploy();
	}

	@Test
	public void testDeployFromInputStream(){
		InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("qingjia.jpdl.xml");
		ProcessEngine processEngine = Configuration.getProcessEngine();
		processEngine.getRepositoryService()
		.createDeployment()
		/**
		 * µÚÒ»¸ö²ÎÊýÊÇÎļþµÄ·¾¶
		 * µÚ¶þ¸ö²ÎÊýÊÇinputStream
		 */
		.addResourceFromInputStream("qingjia.jpdl.xml", inputStream)
		.deploy();
	}

	@Test
	public void testDeployFromZipInputStream(){
		//µÃµ½zipinputStream
		InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("qingjia.zip");
		ZipInputStream zipInputStream = new ZipInputStream(inputStream);
		//Íê³É²¿Êð
		ProcessEngine processEngine = Configuration.getProcessEngine();
		processEngine.getRepositoryService()
		.createDeployment()
		.addResourcesFromZipInputStream(zipInputStream)
		.deploy();
	}

	/**
	 * ¸ù¾ÝdeploymentId²é¿´Á÷³Ì¶¨ÒåͼƬ
	 */
	@Test
	public void testShowImage() throws Exception{
		ProcessEngine processEngine = Configuration.getProcessEngine();
		InputStream inputStream = processEngine.getRepositoryService()
		.getResourceAsStream("1","qingjia.png");

		OutputStream outputStream = new FileOutputStream("d:/processimg.png");
		for(int b=-1;(b=inputStream.read())!=-1;){
			outputStream.write(b);
		}
		inputStream.close();
		outputStream.close();
	}

	/**
	 * ²éѯËùÓеÄÁ÷³Ì²¿Êð
	 */
	@Test
	public void testQueryAllDeployment(){
		ProcessEngine processEngine = Configuration.getProcessEngine();
		List<Deployment> dList = processEngine.getRepositoryService()
		.createDeploymentQuery()
		.list();
		for(Deployment deployment:dList){
			System.out.println(deployment.getId());
		}
	}

	/**
	 * ¸ù¾ÝdeploymentId²éѯÁ÷³Ì²¿Êð
	 */
	@Test
	public void testQueryDeployment(){
		ProcessEngine processEngine =  Configuration.getProcessEngine();
		Deployment deployment = processEngine.getRepositoryService()
		.createDeploymentQuery()
		.deploymentId("20001")
		.uniqueResult();
		System.out.println(deployment.getId());
	}

	/**
	 * ²éѯËùÓеÄÁ÷³Ì¶¨Òå
	 */
	@Test
	public void testQueryPD(){
		ProcessEngine processEngine =  Configuration.getProcessEngine();
		List<ProcessDefinition> pdList = processEngine.getRepositoryService()
		.createProcessDefinitionQuery()
		.list();
		for(ProcessDefinition pd:pdList){
			System.out.print("deploymentId: "+pd.getDeploymentId()+",");
			System.out.print("image: "+pd.getImageResourceName()+",");
			System.out.print("pdkey: "+pd.getKey()+",");
			System.out.print("version: "+pd.getVersion()+",");
			System.out.println("pdid: "+pd.getId());
		}
	}

	/**
	 * ¸ø¶¨Ò»¸ödeploymentID,ɾ³ý¸ÃÁ÷³Ì²¿Êð
	 */
	@Test
	public void testDelete(){
		ProcessEngine processEngine =  Configuration.getProcessEngine();
		processEngine.getRepositoryService()
		.deleteDeploymentCascade("30001");
	}

	/**
	 * ¸ø¶¨Ò»¸öpdkey,ɾ³ýÕû¸öÁ÷³Ì¶¨Òå
	 *    1¡¢¸ù¾Ýpdkey²éѯ³öËùÓеÄÁ÷³Ì¶¨Òå
	 *    2¡¢±éÀú¸øpdkeyϵÄËùÓеÄÁ÷³Ì¶¨Ò壬´Óÿһ¸öÁ÷³Ì¶¨ÒåÖаÑdeploymentIDÌáÈ¡³öÀ´
	 *    3¡¢¸ù¾ÝdeploymentIDɾ³ýÁ÷³Ì¶¨Òå
	 */
	@Test
	public void testDeletePD(){
		ProcessEngine processEngine =  Configuration.getProcessEngine();
		/**
		 * ¸ù¾Ýpdkey»ñÈ¡ËùÓеÄÁ÷³Ì¶¨Òå
		 */
		List<ProcessDefinition> pdList = processEngine.getRepositoryService()
		.createProcessDefinitionQuery()
		.processDefinitionKey("qingjia")
		.list();

		for(ProcessDefinition pd:pdList){
			processEngine.getRepositoryService()
			.deleteDeploymentCascade(pd.getDeploymentId());
		}
	}
}


text:
do
  -- let's ensure the required shared dictionaries are
  -- declared via lua_shared_dict in the Nginx conf

  local constants = require "kong.constants"

  for _, dict in ipairs(constants.DICTS) do
    if not ngx.shared[dict] then
      return error("missing shared dict '" .. dict .. "' in Nginx "          ..
                   "configuration, are you using a custom template? "        ..
                   "Make sure the 'lua_shared_dict " .. dict .. " [SIZE];' " ..
                   "directive is defined.")
    end
  end
end

require("kong.core.globalpatches")()

local dns = require "kong.tools.dns"
local core = require "kong.core.handler"
local Serf = require "kong.serf"
local utils = require "kong.tools.utils"
local Events = require "kong.core.events"
local responses = require "kong.tools.responses"
local constants = require "kong.constants"
local singletons = require "kong.singletons"
local DAOFactory = require "kong.dao.factory"
local ngx_balancer = require "ngx.balancer"
local plugins_iterator = require "kong.core.plugins_iterator"
local balancer_execute = require("kong.core.balancer").execute

local ipairs           = ipairs
local get_last_failure = ngx_balancer.get_last_failure
local set_current_peer = ngx_balancer.set_current_peer
local set_timeouts     = ngx_balancer.set_timeouts
local set_more_tries   = ngx_balancer.set_more_tries

local function attach_hooks(events, hooks)
  for k, v in pairs(hooks) do
    events:subscribe(k, v)
  end
end

local function load_plugins(kong_conf, dao, events)
  local in_db_plugins, sorted_plugins = {}, {}

  ngx.log(ngx.DEBUG, "Discovering used plugins")

  local rows, err_t = dao.plugins:find_all()
  if not rows then
    return nil, tostring(err_t)
  end

  for _, row in ipairs(rows) do in_db_plugins[row.name] = true end

  -- check all plugins in DB are enabled/installed
  for plugin in pairs(in_db_plugins) do
    if not kong_conf.plugins[plugin] then
      return nil, plugin .. " plugin is in use but not enabled"
    end
  end

  -- load installed plugins
  for plugin in pairs(kong_conf.plugins) do
    local ok, handler = utils.load_module_if_exists("kong.plugins." .. plugin .. ".handler")
    if not ok then
      return nil, plugin .. " plugin is enabled but not installed;\n" .. handler
    end

    local ok, schema = utils.load_module_if_exists("kong.plugins." .. plugin .. ".schema")
    if not ok then
      return nil, "no configuration schema found for plugin: " .. plugin
    end

    ngx.log(ngx.DEBUG, "Loading plugin: " .. plugin)

    sorted_plugins[#sorted_plugins+1] = {
      name = plugin,
      handler = handler(),
      schema = schema
    }

    -- Attaching hooks
    local ok, hooks = utils.load_module_if_exists("kong.plugins." .. plugin .. ".hooks")
    if ok then
      attach_hooks(events, hooks)
    end
  end

  -- sort plugins by order of execution
  table.sort(sorted_plugins, function(a, b)
    local priority_a = a.handler.PRIORITY or 0
    local priority_b = b.handler.PRIORITY or 0
    return priority_a > priority_b
  end)

  -- add reports plugin if not disabled
  if kong_conf.anonymous_reports then
    local reports = require "kong.core.reports"
    reports.toggle(true)
    sorted_plugins[#sorted_plugins+1] = {
      name = "reports",
      handler = reports
    }
  end

  return sorted_plugins
end

-- Kong public context handlers.
-- @section kong_handlers

local Kong = {}

function Kong.init()
  local pl_path = require "pl.path"
  local conf_loader = require "kong.conf_loader"

  -- retrieve kong_config
  local conf_path = pl_path.join(ngx.config.prefix(), ".kong_env")
  local config = assert(conf_loader(conf_path))

  local events = Events() -- retrieve node plugins
  local dao = assert(DAOFactory.new(config, events)) -- instanciate long-lived DAO
  assert(dao:init())
  assert(dao:run_migrations()) -- migrating in case embedded in custom nginx

  -- populate singletons
  singletons.dns = dns(config)
  singletons.loaded_plugins = assert(load_plugins(config, dao, events))
  singletons.serf = Serf.new(config, dao)
  singletons.dao = dao
  singletons.events = events
  singletons.configuration = config

  attach_hooks(events, require "kong.core.hooks")

  assert(core.build_router())
end

function Kong.init_worker()
  -- special math.randomseed from kong.core.globalpatches
  -- not taking any argument. Must be called only once
  -- and in the init_worker phase, to avoid duplicated
  -- seeds.
  math.randomseed()

  -- init DAO

  local ok, err = singletons.dao:init_worker()
  if not ok then
    ngx.log(ngx.CRIT, "could not init DB: ", err)
    return
  end

  -- init inter-worker events

  local worker_events = require "resty.worker.events"

  local handler = function(data, event, source, pid)
    if data and data.collection == "apis" then
      assert(core.build_router())

    elseif source and source == constants.CACHE.CLUSTER then
      singletons.events:publish(event, data)
    end
  end

  worker_events.register(handler)

  local ok, err = worker_events.configure {
    shm = "process_events", -- defined by "lua_shared_dict"
    timeout = 5,            -- life time of event data in shm
    interval = 1,           -- poll interval (seconds)

    wait_interval = 0.010,  -- wait before retry fetching event data
    wait_max = 0.5,         -- max wait time before discarding event
  }
  if not ok then
    ngx.log(ngx.CRIT, "could not start inter-worker events: ", err)
    return
  end

  core.init_worker.before()

  -- run plugins init_worker context

  for _, plugin in ipairs(singletons.loaded_plugins) do
    plugin.handler:init_worker()
  end
end

function Kong.ssl_certificate()
  local ctx = ngx.ctx
  core.certificate.before(ctx)

  for plugin, plugin_conf in plugins_iterator(singletons.loaded_plugins, true) do
    plugin.handler:certificate(plugin_conf)
  end
end

function Kong.balancer()
  local ctx = ngx.ctx
  local addr = ctx.balancer_address
  local tries = addr.tries
  local current_try = {}
  addr.try_count = addr.try_count + 1
  tries[addr.try_count] = current_try

  core.balancer.before()

  if addr.try_count > 1 then
    -- only call balancer on retry, first one is done in `core.access.after` which runs
    -- in the ACCESS context and hence has less limitations than this BALANCER context
    -- where the retries are executed

    -- record failure data
    local previous_try = tries[addr.try_count - 1]
    previous_try.state, previous_try.code = get_last_failure()

    local ok, err = balancer_execute(addr)
    if not ok then
      ngx.log(ngx.ERR, "failed to retry the dns/balancer resolver for ",
              addr.upstream.host, "' with: ", tostring(err))

      return responses.send(500)
    end

  else
    -- first try, so set the max number of retries
    local retries = addr.retries
    if retries > 0 then
      set_more_tries(retries)
    end
  end

  current_try.ip   = addr.ip
  current_try.port = addr.port

  -- set the targets as resolved
  local ok, err = set_current_peer(addr.ip, addr.port)
  if not ok then
    ngx.log(ngx.ERR, "failed to set the current peer (address: ",
            tostring(addr.ip), " port: ", tostring(addr.port),"): ",
            tostring(err))

    return responses.send(500)
  end

  ok, err = set_timeouts(addr.connect_timeout / 1000,
                         addr.send_timeout / 1000,
                         addr.read_timeout / 1000)
  if not ok then
    ngx.log(ngx.ERR, "could not set upstream timeouts: ", err)
  end

  core.balancer.after()
end

function Kong.rewrite()
  local ctx = ngx.ctx
  core.rewrite.before(ctx)

  -- we're just using the iterator, as in this rewrite phase no consumer nor
  -- api will have been identified, hence we'll just be executing the global
  -- plugins
  for plugin, plugin_conf in plugins_iterator(singletons.loaded_plugins, true) do
    plugin.handler:rewrite(plugin_conf)
  end

  core.rewrite.after(ctx)
end

function Kong.access()
  local ctx = ngx.ctx
  core.access.before(ctx)

  for plugin, plugin_conf in plugins_iterator(singletons.loaded_plugins, true) do
    plugin.handler:access(plugin_conf)
  end

  core.access.after(ctx)
end

function Kong.header_filter()
  local ctx = ngx.ctx
  core.header_filter.before(ctx)

  for plugin, plugin_conf in plugins_iterator(singletons.loaded_plugins) do
    plugin.handler:header_filter(plugin_conf)
  end

  core.header_filter.after(ctx)
end

function Kong.body_filter()
  local ctx = ngx.ctx
  for plugin, plugin_conf in plugins_iterator(singletons.loaded_plugins) do
    plugin.handler:body_filter(plugin_conf)
  end

  core.body_filter.after(ctx)
end

function Kong.log()
  local ctx = ngx.ctx
  for plugin, plugin_conf in plugins_iterator(singletons.loaded_plugins) do
    plugin.handler:log(plugin_conf)
  end

  core.log.after(ctx)
end

return Kong


text:
The sample source code below will teach you how to extract pages from pdf with pdf extractor sdk in VB.NET. ByteScout PDF Suite is the bundle that provides six different SDK libraries to work with PDF from generating rich PDF reports to extracting data from PDF documents and converting them to HTML. This bundle includes PDF (Generator) SDK, PDF Renderer SDK, PDF Extractor SDK, PDF to HTML SDK, PDF Viewer SDK and PDF Generator SDK for Javascript and you can use it to extract pages from pdf with pdf extractor sdk with VB.NET.

The following code snippet for ByteScout PDF Suite works best when you need to quickly extract pages from pdf with pdf extractor sdk in your VB.NET application. Follow the instructions from scratch to work and copy the VB.NET code. Enjoy writing a code with ready-to-use sample codes in VB.NET.

Our website gives trial version of ByteScout PDF Suite for free. It also includes documentation and source code samples.

## REQUEST FREE TECH SUPPORT

[Click here to get in touch](https://bytescout.zendesk.com/hc/en-us/requests/new?subject=ByteScout%20PDF%20Suite%20Question)

or just send email to [support@bytescout.com](mailto:support@bytescout.com?subject=ByteScout%20PDF%20Suite%20Question)

## ON-PREMISE OFFLINE SDK

[Get Your 60 Day Free Trial](https://bytescout.com/download/web-installer?utm_source=github-readme)
[Explore SDK Docs](https://bytescout.com/documentation/index.html?utm_source=github-readme)
[Sign Up For Online Training](https://academy.bytescout.com/)

## ON-DEMAND REST WEB API

[Get your API key](https://pdf.co/documentation/api?utm_source=github-readme)
[Explore Web API Documentation](https://pdf.co/documentation/api?utm_source=github-readme)
[Explore Web API Samples](https://github.com/bytescout/ByteScout-SDK-SourceCode/tree/master/PDF.co%20Web%20API)

## VIDEO REVIEW

[https://www.youtube.com/watch?v=NEwNs2b9YN8](https://www.youtube.com/watch?v=NEwNs2b9YN8)

<!-- code block begin -->

##### ****Program.vb:**

```
' This example demonstrates various PDF document splitting scenarios:
' - extract a single page;
' - split in two parts;
' - split by ranges specified in text form: "1-5,6,7-10,11-".

Imports System.IO
Imports Bytescout.PDFExtractor

Class Program
	Friend Shared Sub Main(args As String())
		Dim inputFile As String = ".\sample.pdf"

		Using splitter As New DocumentSplitter("demo", "demo")
			splitter.OptimizeSplittedDocuments = True

			' Extracting specific page:
			' =========================

			splitter.ExtractPage(inputFile, "page3.pdf", 3)
			' (!) Note: page number is 1-based.
			Console.WriteLine("Extracted page 3 to file ""page3.pdf""")
			Console.WriteLine()

			' Split in two parts:
			' ===================

			splitter.Split(inputFile, "part1.pdf", "part2.pdf", 3)
			' (!) Note: page number is 1-based.
			Console.WriteLine("Splitted at page 3 to files ""part1.pdf"" and ""part2.pdf""")
			Console.WriteLine()

			' Split by ranges:
			' ================

			Dim files As String() = splitter.Split(inputFile, "1-3,4-6,7,8-")
			' (!) Note: page numbers are 1-based; ending "-" means "to the end".
			Console.WriteLine("Splitted by ranges: ")
			For Each file As String In files
				Console.WriteLine("    " & Path.GetFileName(file))
			Next
		End Using

		Console.WriteLine()
		Console.WriteLine("Press any key...")
		Console.ReadKey()
	End Sub
End Class

```

<!-- code block end -->

<!-- code block begin -->

##### ****SplittingExample.Converted.VS2005.vbproj:**

```
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.50727</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{ED783E81-6D76-4015-9902-333096BD4B5C}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>SplittingExample</RootNamespace>
    <AssemblyName>SplittingExample</AssemblyName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG,TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.Targets" />
  <ItemGroup>
    <Import Include="Microsoft.VisualBasic" />
    <Import Include="System" />
    <Reference Include="Bytescout.PDFExtractor, Version=1.0.0.12, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="System" />
    <Compile Include="Program.vb" />
    <Content Include="sample.pdf">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Folder Include="Properties\" />
  </ItemGroup>
</Project>
```

<!-- code block end -->

<!-- code block begin -->

##### ****SplittingExample.Converted.VS2008.vbproj:**

```
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.50727</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{ED783E81-6D76-4015-9902-333096BD4B5C}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>SplittingExample</RootNamespace>
    <AssemblyName>SplittingExample</AssemblyName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG,TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.Targets" />
  <ItemGroup>
    <Import Include="Microsoft.VisualBasic" />
    <Import Include="System" />
    <Reference Include="Bytescout.PDFExtractor, Version=1.0.0.12, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="System" />
    <Compile Include="Program.vb" />
    <Content Include="sample.pdf">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Folder Include="Properties\" />
  </ItemGroup>
</Project>
```

<!-- code block end -->

<!-- code block begin -->

##### ****SplittingExample.Converted.VS2010.vbproj:**

```
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>
    </ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{ED783E81-6D76-4015-9902-333096BD4B5C}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>SplittingExample</RootNamespace>
    <AssemblyName>SplittingExample</AssemblyName>
    <OldToolsVersion>3.5</OldToolsVersion>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG,TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.Targets" />
  <ItemGroup>
    <Import Include="Microsoft.VisualBasic" />
    <Import Include="System" />
    <Reference Include="Bytescout.PDFExtractor, Version=1.0.0.12, Culture=neutral, processorArchitecture=MSIL">
      <SpecificVersion>False</SpecificVersion>
    </Reference>
    <Reference Include="System" />
    <Compile Include="Program.vb" />
    <Content Include="sample.pdf">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
    <Folder Include="Properties\" />
  </ItemGroup>
</Project>
```

<!-- code block end -->


text:
package org.jboss.pnc.bpm;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.jboss.pnc.bpm.model.BpmEvent;
import org.jboss.pnc.common.concurrent.MDCWrappers;
import org.jboss.pnc.common.json.moduleconfig.BpmModuleConfig;
import org.jboss.pnc.common.logging.MDCUtils;
import org.jboss.pnc.spi.exception.CoreException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Consumer;

import static java.util.Objects.requireNonNull;

/**
 * Parent type of all BPM tasks. Task is a representation of BPM process execution, keeps track of the remote process
 * instance and handles notifications. Class implements Comparable based on the taskId, so they can be sorted at REST
 * endpoint. BPM tasks do not have to be thread safe.
 *
 * @author Jakub Senko
 */
@EqualsAndHashCode(of = "taskId")
public abstract class BpmTask implements Comparable<BpmTask> {

    private static final Logger log = LoggerFactory.getLogger(BpmTask.class);

    protected static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * This is an internal identifier, not one provided by BPM server.
     */
    private Integer taskId;

    private Long processInstanceId;

    @Getter
    private final List<BpmEvent> events = new ArrayList<>();

    private String processName;

    protected BpmModuleConfig config;

    private ConcurrentMap<BpmEventType, List<Consumer<?>>> listeners = new ConcurrentHashMap<>();

    /**
     * Users OAuth token used to authenticate requests on remote services
     */
    private final String accessToken;
    private Optional<Connector> connector = Optional.empty();
    private boolean jsonEncodedProcessParameters = true;

    public BpmTask(String accessToken) {
        this.accessToken = accessToken;
    }

    public String getProcessName() {
        return processName;
    }

    /* package */ void setProcessName(String processName) {
        this.processName = processName;
    }

    /**
     * Get the name of the BPM process for this task. Warning: The process MUST be asynchronous so it does not block BPM
     * manager.
     */
    protected abstract String getProcessId();

    /**
     * Provide parameters to the BPM process. The JSON representation of this map will be available in the BPM process
     * as "processParameters" variable. Some parameters, such as "taskId" are automatically added, not into the
     * "processParameters" variable, but 'one level higher' and directly accessible from process variables.
     *
     * @return a map of process parameters
     * @throws CoreException
     */
    protected abstract Serializable getProcessParameters() throws CoreException;

    /* package */ void setBpmConfig(BpmModuleConfig config) {
        this.config = config;
    }

    public Integer getTaskId() {
        return taskId;
    }

    /* package */ void setTaskId(int taskId) {
        this.taskId = taskId;
    }

    public Long getProcessInstanceId() {
        return processInstanceId;
    }

    /* package */ void setProcessInstanceId(Long processInstanceId) {
        this.processInstanceId = processInstanceId;
    }

    /**
     * Listen to notifications from BPM process for this task.
     *
     * @param eventType event to follow
     */
    public <T extends BpmEvent> void addListener(BpmEventType eventType, Consumer<T> listener) {
        List<Consumer<?>> consumers = listeners.computeIfAbsent(eventType, (k) -> new ArrayList<>());
        consumers.add(MDCWrappers.wrap(listener));
    }

    public <T extends BpmEvent> void notify(BpmEventType eventType, T data) {
        List<Consumer<?>> listeners = this.listeners.computeIfAbsent(eventType, (k) -> new ArrayList<>());
        log.debug(
                "will notify bpm listeners for eventType: {}, matching listeners: {}, all listeners: {}",
                eventType,
                listeners,
                this.listeners);
        listeners.forEach(
                listener -> {
                    // Cast is OK because there is no unchecked method declaration to put wrong types
                    ((Consumer<T>) listener).accept(data);
                });
        events.add(data);
    }

    /**
     * Extend process parameters from the task with additional useful information, such as pncBaseUrl and taskId, needed
     * for notifications. Before use, taskId MUST be assigned.
     *
     * @throws CoreException
     */
    Map<String, Object> getExtendedProcessParameters() throws CoreException {
        Serializable processParameters = getProcessParameters();
        requireNonNull(processParameters);
        Map<String, Object> actualParameters = new HashMap<>();
        if (isJsonEncodedProcessParameters()) {
            try {
                actualParameters.put("processParameters", MAPPER.writeValueAsString(processParameters));
            } catch (JsonProcessingException e) {
                throw new CoreException(
                        "Could not serialize process processParameters '" + processParameters + "'.",
                        e);
            }
        } else {
            actualParameters.put("processParameters", processParameters);
        }

        // global not process related parameters
        actualParameters.put("taskId", taskId);
        actualParameters.put("usersAuthToken", accessToken);
        MDCUtils.getUserId().ifPresent(v -> {
            log.debug("Setting process parameter userId: {}", v);
            actualParameters.put("userId", v);
        });
        MDCUtils.getRequestContext().ifPresent(v -> {
            log.debug("Setting process parameter logRequestContext: {}", v);
            actualParameters.put("logRequestContext", v);
        });
        MDCUtils.getProcessContext().ifPresent(v -> {
            log.debug("Setting process parameter logProcessContext: {}", v);
            actualParameters.put("logProcessContext", v);
        });
        return actualParameters;
    }

    public void setJsonEncodedProcessParameters(boolean jsonEncodedProcessParameters) {
        this.jsonEncodedProcessParameters = jsonEncodedProcessParameters;
    }

    protected boolean isJsonEncodedProcessParameters() {
        return jsonEncodedProcessParameters;
    }

    public String getAccessToken() {
        return accessToken;
    }

    @Override
    public int compareTo(BpmTask other) {
        requireNonNull(other);
        if (taskId == null)
            return other.getTaskId() == null ? 0 : -1;
        if (other.getTaskId() == null)
            return 1;
        return taskId.compareTo(other.getTaskId());
    }

    @Override
    public String toString() {
        return "BpmTask{" + "taskId=" + taskId + ", processInstanceId=" + processInstanceId + ", events=" + events
                + ", processName='" + processName + '\'' + ", config=" + config + ", listeners=" + listeners
                + ", accessToken='***'" + '}';
    }

    public Optional<Connector> getConnector() {
        return connector;
    }

    public void setConnector(Connector connector) {
        this.connector = Optional.ofNullable(connector);
    }
}


text:
package web

import (
	"fmt"
	"net/http"
	"path/filepath"

	"github.com/gin-gonic/gin"
	"github.com/hobeone/tv2go/db"
	"github.com/hobeone/tv2go/naming"
	"github.com/hobeone/tv2go/storage"
	"github.com/hobeone/tv2go/types"
)

// http://wiki.sabnzbd.org/user-scripts
type postprocessReq struct {
	Path       string `json:"path" form:"path" binding:"required"`
	SourceName string `json:"source_name" form:"source_name"`
}

func writeAndFlush(c *gin.Context, str string, args ...interface{}) {
	fmt.Fprintf(c.Writer, str+"\n", args...)
	c.Writer.Flush()
}

func (server *Server) getShowFromName(c *gin.Context, name string) (*db.Show, int64, error) {
	dbshow, season, err := server.dbHandle.GetShowByAllNames(name)
	if err == nil {
		writeAndFlush(c, "Found show with name %s in database.", dbshow.Name)
		return dbshow, season, nil
	}
	writeAndFlush(c, "Couldn't find show with name in db: '%s'.", name)

	sceneName := naming.FullSanitizeSceneName(name)
	writeAndFlush(c, "Couldn't find show in exception list")

	writeAndFlush(c, "Searching indexers for %s", sceneName)
	for name, idxer := range server.indexers {
		writeAndFlush(c, "Search %s for %s", name, sceneName)
		shows, err := idxer.Search(sceneName)
		if err != nil {
			writeAndFlush(c, "Error searching indexer for %s: %s", sceneName, err)
			continue
		}
		writeAndFlush(c, "Got %d results from indexer %s", len(shows), name)
		for _, show := range shows {
			dbshow, err = server.dbHandle.GetShowByName(show.Name)
			if err != nil {
				writeAndFlush(c, "Error searching DB for show with name %s: %s", show.Name, err)
				continue
			}
			writeAndFlush(c, "Found show in DB with name %s", dbshow.Name)
			// Check that indexerid's match
			//if dbshow.IndexerID != show.IndexerID {
			//	writeAndFlush(c, "Indexer id for dbshow and indexer result differ (%d != %d), skipping.", dbshow.IndexerID, show.IndexerID)
			//}
			return dbshow, -1, nil
		}
	}
	return nil, -1, fmt.Errorf("Couldn't match %s with any known show", name)
}

// Postprocess takes the given path, tries to match it with a show and episode
// and then moves it to where it should go.
func (server *Server) Postprocess(c *gin.Context) {
	var reqJSON postprocessReq

	if !c.Bind(&reqJSON) {
		genError(c, http.StatusBadRequest, c.Errors.String())
		return
	}

	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	c.Writer.Flush()

	// Does directory exist and is it readable
	// Get media files from dir
	// for each media file
	//   map to show
	//   map to season/episode
	//   get show & episode
	//   move file
	//   update episode

	if !server.Broker.Readable(reqJSON.Path) {
		c.String(http.StatusBadRequest, "Can't open path '%s'\n", reqJSON.Path)
		return
	}
	mediaFiles, err := storage.MediaFilesInDir(reqJSON.Path)
	if err != nil {
		c.String(http.StatusInternalServerError, "Couldn't get files from %s: %s", reqJSON.Path, err)
		return
	}
	if len(mediaFiles) == 0 {
		writeAndFlush(c, "Couldn't find any media files in '%s'", reqJSON.Path)
		return
	}

	goodresults := []naming.ParseResult{}

	np := naming.NewNameParser(naming.AllRegexes)
	for _, file := range mediaFiles {
		writeAndFlush(c, "Trying to parse %s", file)
		nameres := np.ParseFile(file)
		if nameres.SeriesName == "" {
			writeAndFlush(c, "Couldn't parse series name from %s: skipping", file)
			continue
		}
		if len(nameres.AbsoluteEpisodeNumbers) == 0 && len(nameres.EpisodeNumbers) == 0 {
			writeAndFlush(c, "Couldn't parse episode numbers from '%s'", reqJSON.Path)
			continue
		}
		writeAndFlush(c, "Parsed to %+v", nameres)
		goodresults = append(goodresults, nameres)
	}
	if len(goodresults) == 0 {
		writeAndFlush(c, "Couldn't parse any files in '%s'", reqJSON.Path)
		return
	}

	for _, res := range goodresults {
		dbshow, season, err := server.getShowFromName(c, res.SeriesName)
		if season > -1 {
			res.SeasonNumber = season
		}
		if err != nil {
			writeAndFlush(c, "Couldn't find show with name: '%s'.", res.SeriesName)
			continue
		}

		epnum := res.FirstEpisode()
		dbep, err := server.dbHandle.GetEpisodeByShowSeasonAndNumber(
			dbshow.ID, res.SeasonNumber, epnum)

		if err != nil {
			writeAndFlush(c, "Couldn't find an season/episode for %d, %v, %v", dbshow.ID, res.SeasonNumber, epnum)
			continue
		}

		ext := filepath.Ext(res.OriginalName)
		//loc, err := dbep.GetLocation()
		//Season 01/Show Name-S01E01-Ep Title.ext"
		loc := "Season %02d/%s - S%02dE%02d - %s%s"
		expandedLoc := fmt.Sprintf(loc, dbep.Season, dbshow.Name, dbep.Season, dbep.Episode, dbep.Name, ext)

		expandedLoc = filepath.Join(dbshow.Location, expandedLoc)
		// TODO: import if forced, or quality is equal or better
		err = server.Broker.FileReadable(expandedLoc)
		if err == nil {
			writeAndFlush(c, "File already exists at '%s'", expandedLoc)
			continue
		}

		writeAndFlush(c, "Moving file %s to %s", res.OriginalName, expandedLoc)

		// Change this to provide progress over a channel so we can write progress
		// to the client.

		err = server.Broker.MoveFile(res.OriginalName, expandedLoc)
		if err != nil {
			writeAndFlush(c, "Error moving file to location: %s", err)
			continue
		}

		dbep.Location = expandedLoc
		dbep.Status = types.DOWNLOADED
		err = server.dbHandle.SaveEpisode(dbep)
		if err != nil {
			writeAndFlush(c, "Error saving new episode location: %s", err)
			continue
		}
	}
	c.String(200, "Added episodes.")
}


text:
    <modal>

        <modal-title>Photo Upload</modal-title>

        <modal-content>

            <photo-upload></photo-upload>

        </modal-content>

    </modal>


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.SourceGeneration;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
{
    internal sealed class SyntaxReceiverStrategy<T> : ISyntaxSelectionStrategy<T>
    {
        private readonly SyntaxContextReceiverCreator _receiverCreator;
        private readonly Action<IIncrementalGeneratorOutputNode> _registerOutput;
        private readonly ISyntaxHelper _syntaxHelper;

        public SyntaxReceiverStrategy(
            SyntaxContextReceiverCreator receiverCreator,
            Action<IIncrementalGeneratorOutputNode> registerOutput,
            ISyntaxHelper syntaxHelper)
        {
            _receiverCreator = receiverCreator;
            _registerOutput = registerOutput;
            _syntaxHelper = syntaxHelper;
        }

        public ISyntaxInputBuilder GetBuilder(StateTableStore table, object key, bool trackIncrementalSteps, string? name, IEqualityComparer<T>? comparer) => new Builder(this, key, table, trackIncrementalSteps);

        private sealed class Builder : ISyntaxInputBuilder
        {
            private readonly SyntaxReceiverStrategy<T> _owner;
            private readonly object _key;
            private readonly NodeStateTable<ISyntaxContextReceiver?>.Builder _nodeStateTable;
            private readonly ISyntaxContextReceiver? _receiver;
            private readonly GeneratorSyntaxWalker? _walker;
            private TimeSpan lastElapsedTime;

            public Builder(SyntaxReceiverStrategy<T> owner, object key, StateTableStore driverStateTable, bool trackIncrementalSteps)
            {
                _owner = owner;
                _key = key;
                _nodeStateTable = driverStateTable.GetStateTableOrEmpty<ISyntaxContextReceiver?>(_key).ToBuilder(stepName: null, trackIncrementalSteps);
                try
                {
                    _receiver = owner._receiverCreator();
                }
                catch (Exception e)
                {
                    throw new UserFunctionException(e);
                }

                if (_receiver is object)
                {
                    _walker = new GeneratorSyntaxWalker(_receiver, owner._syntaxHelper);
                }
            }

            private bool TrackIncrementalSteps => _nodeStateTable.TrackIncrementalSteps;

            public void SaveStateAndFree(StateTableStore.Builder tables)
            {
                _nodeStateTable.AddEntry(_receiver, EntryState.Modified, lastElapsedTime, TrackIncrementalSteps ? System.Collections.Immutable.ImmutableArray<(IncrementalGeneratorRunStep, int)>.Empty : default, EntryState.Modified);
                tables.SetTable(_key, _nodeStateTable.ToImmutableAndFree());
            }

            public void VisitTree(
                Lazy<SyntaxNode> root,
                EntryState state,
                Lazy<SemanticModel>? model,
                CancellationToken cancellationToken)
            {
                if (_walker is not null && state != EntryState.Removed)
                {
                    Debug.Assert(model is not null);
                    try
                    {
                        var stopwatch = SharedStopwatch.StartNew();
                        _walker.VisitWithModel(model, root.Value);
                        if (TrackIncrementalSteps)
                        {
                            lastElapsedTime = stopwatch.Elapsed;
                        }
                    }
                    catch (Exception e) when (!ExceptionUtilities.IsCurrentOperationBeingCancelled(e, cancellationToken))
                    {
                        throw new UserFunctionException(e);
                    }
                }
            }
        }
    }
}


text:
export interface EventTypeOptions {
  browserEventName?: string;
  createEventArgs?: (event: Event) => unknown;
}

const eventTypeRegistry: Map<string, EventTypeOptions> = new Map();
const browserEventNamesToAliases: Map<string, string[]> = new Map();
const createBlankEventArgsOptions: EventTypeOptions = { createEventArgs: () => ({}) };

export const eventNameAliasRegisteredCallbacks: ((aliasEventName: string, browserEventName) => void)[] = [];

export function registerCustomEventType(eventName: string, options: EventTypeOptions): void {
  if (!options) {
    throw new Error('The options parameter is required.');
  }

  // There can't be more than one registration for the same event name because then we wouldn't
  // know which eventargs data to supply.
  if (eventTypeRegistry.has(eventName)) {
    throw new Error(`The event '${eventName}' is already registered.`);
  }

  // If applicable, register this as an alias of the given browserEventName
  if (options.browserEventName) {
    const aliasGroup = browserEventNamesToAliases.get(options.browserEventName);
    if (aliasGroup) {
      aliasGroup.push(eventName);
    } else {
      browserEventNamesToAliases.set(options.browserEventName, [eventName]);
    }

    // For developer convenience, it's allowed to register the custom event type *after*
    // some listeners for it are already present. Once the event name alias gets registered,
    // we have to notify any existing event delegators so they can update their delegated
    // events list.
    eventNameAliasRegisteredCallbacks.forEach(callback => callback(eventName, options.browserEventName));
  }

  eventTypeRegistry.set(eventName, options);
}

export function getEventTypeOptions(eventName: string): EventTypeOptions | undefined {
  return eventTypeRegistry.get(eventName);
}

export function getEventNameAliases(eventName: string): string[] | undefined {
  return browserEventNamesToAliases.get(eventName);
}

export function getBrowserEventName(possibleAliasEventName: string): string {
  const eventOptions = eventTypeRegistry.get(possibleAliasEventName);
  return eventOptions?.browserEventName || possibleAliasEventName;
}

function registerBuiltInEventType(eventNames: string[], options: EventTypeOptions) {
  eventNames.forEach(eventName => eventTypeRegistry.set(eventName, options));
}

registerBuiltInEventType(['input', 'change'], {
  createEventArgs: parseChangeEvent,
});

registerBuiltInEventType([
  'copy',
  'cut',
  'paste',
], {
  createEventArgs: e => parseClipboardEvent(e as ClipboardEvent),
});

registerBuiltInEventType([
  'drag',
  'dragend',
  'dragenter',
  'dragleave',
  'dragover',
  'dragstart',
  'drop',
], {
  createEventArgs: e => parseDragEvent(e as DragEvent),
});

registerBuiltInEventType([
  'focus',
  'blur',
  'focusin',
  'focusout',
], {
  createEventArgs: e => parseFocusEvent(e as FocusEvent),
});

registerBuiltInEventType([
  'keydown',
  'keyup',
  'keypress',
], {
  createEventArgs: e => parseKeyboardEvent(e as KeyboardEvent),
});

registerBuiltInEventType([
  'contextmenu',
  'click',
  'mouseover',
  'mouseout',
  'mousemove',
  'mousedown',
  'mouseup',
  'mouseleave',
  'mouseenter',
  'dblclick',
], {
  createEventArgs: e => parseMouseEvent(e as MouseEvent),
});

registerBuiltInEventType(['error'], {
  createEventArgs: e => parseErrorEvent(e as ErrorEvent),
});

registerBuiltInEventType([
  'loadstart',
  'timeout',
  'abort',
  'load',
  'loadend',
  'progress',
], {
  createEventArgs: e => parseProgressEvent(e as ProgressEvent),
});

registerBuiltInEventType([
  'touchcancel',
  'touchend',
  'touchmove',
  'touchenter',
  'touchleave',
  'touchstart',
], {
  createEventArgs: e => parseTouchEvent(e as TouchEvent),
});

registerBuiltInEventType([
  'gotpointercapture',
  'lostpointercapture',
  'pointercancel',
  'pointerdown',
  'pointerenter',
  'pointerleave',
  'pointermove',
  'pointerout',
  'pointerover',
  'pointerup',
], {
  createEventArgs: e => parsePointerEvent(e as PointerEvent),
});

registerBuiltInEventType(['wheel', 'mousewheel'], {
  createEventArgs: e => parseWheelEvent(e as WheelEvent),
});

registerBuiltInEventType(['toggle'], createBlankEventArgsOptions);

function parseChangeEvent(event: Event): ChangeEventArgs {
  const element = event.target as Element;
  if (isTimeBasedInput(element)) {
    const normalizedValue = normalizeTimeBasedValue(element);
    return { value: normalizedValue };
  } else if (isMultipleSelectInput(element)) {
    const selectElement = element as HTMLSelectElement;
    const selectedValues = Array.from(selectElement.options)
      .filter(option => option.selected)
      .map(option => option.value);
    return { value: selectedValues };
  } else {
    const targetIsCheckbox = isCheckbox(element);
    const newValue = targetIsCheckbox ? !!element['checked'] : element['value'];
    return { value: newValue };
  }
}

function parseWheelEvent(event: WheelEvent): WheelEventArgs {
  return {
    ...parseMouseEvent(event),
    deltaX: event.deltaX,
    deltaY: event.deltaY,
    deltaZ: event.deltaZ,
    deltaMode: event.deltaMode,
  };
}

function parsePointerEvent(event: PointerEvent): PointerEventArgs {
  return {
    ...parseMouseEvent(event),
    pointerId: event.pointerId,
    width: event.width,
    height: event.height,
    pressure: event.pressure,
    tiltX: event.tiltX,
    tiltY: event.tiltY,
    pointerType: event.pointerType,
    isPrimary: event.isPrimary,
  };
}

function parseTouchEvent(event: TouchEvent): TouchEventArgs {
  return {
    detail: event.detail,
    touches: parseTouch(event.touches),
    targetTouches: parseTouch(event.targetTouches),
    changedTouches: parseTouch(event.changedTouches),
    ctrlKey: event.ctrlKey,
    shiftKey: event.shiftKey,
    altKey: event.altKey,
    metaKey: event.metaKey,
    type: event.type,
  };
}

function parseFocusEvent(event: FocusEvent): FocusEventArgs {
  return {
    type: event.type,
  };
}

function parseClipboardEvent(event: ClipboardEvent): ClipboardEventArgs {
  return {
    type: event.type,
  };
}

function parseProgressEvent(event: ProgressEvent<EventTarget>): ProgressEventArgs {
  return {
    lengthComputable: event.lengthComputable,
    loaded: event.loaded,
    total: event.total,
    type: event.type,
  };
}

function parseErrorEvent(event: ErrorEvent): ErrorEventArgs {
  return {
    message: event.message,
    filename: event.filename,
    lineno: event.lineno,
    colno: event.colno,
    type: event.type,
  };
}

function parseKeyboardEvent(event: KeyboardEvent): KeyboardEventArgs {
  return {
    key: event.key,
    code: event.code,
    location: event.location,
    repeat: event.repeat,
    ctrlKey: event.ctrlKey,
    shiftKey: event.shiftKey,
    altKey: event.altKey,
    metaKey: event.metaKey,
    type: event.type,
  };
}

function parseDragEvent(event: DragEvent): DragEventArgs {
  return {
    ...parseMouseEvent(event),
    dataTransfer: event.dataTransfer ? {
      dropEffect: event.dataTransfer.dropEffect,
      effectAllowed: event.dataTransfer.effectAllowed,
      files: Array.from(event.dataTransfer.files).map(f => f.name),
      items: Array.from(event.dataTransfer.items).map(i => ({ kind: i.kind, type: i.type })),
      types: event.dataTransfer.types,
    } : null,
  };
}

function parseTouch(touchList: TouchList): TouchPoint[] {
  const touches: TouchPoint[] = [];

  for (let i = 0; i < touchList.length; i++) {
    const touch = touchList[i];
    touches.push({
      identifier: touch.identifier,
      clientX: touch.clientX,
      clientY: touch.clientY,
      screenX: touch.screenX,
      screenY: touch.screenY,
      pageX: touch.pageX,
      pageY: touch.pageY,
    });
  }
  return touches;
}

function parseMouseEvent(event: MouseEvent): MouseEventArgs {
  return {
    detail: event.detail,
    screenX: event.screenX,
    screenY: event.screenY,
    clientX: event.clientX,
    clientY: event.clientY,
    offsetX: event.offsetX,
    offsetY: event.offsetY,
    pageX: event.pageX,
    pageY: event.pageY,
    movementX: event.movementX,
    movementY: event.movementY,
    button: event.button,
    buttons: event.buttons,
    ctrlKey: event.ctrlKey,
    shiftKey: event.shiftKey,
    altKey: event.altKey,
    metaKey: event.metaKey,
    type: event.type,
  };
}

function isCheckbox(element: Element | null): boolean {
  return !!element && element.tagName === 'INPUT' && element.getAttribute('type') === 'checkbox';
}

const timeBasedInputs = [
  'date',
  'datetime-local',
  'month',
  'time',
  'week',
];

function isTimeBasedInput(element: Element): element is HTMLInputElement {
  return timeBasedInputs.indexOf(element.getAttribute('type')!) !== -1;
}

function isMultipleSelectInput(element: Element): element is HTMLSelectElement {
  return element instanceof HTMLSelectElement && element.type === 'select-multiple';
}

function normalizeTimeBasedValue(element: HTMLInputElement): string {
  const value = element.value;
  const type = element.type;
  switch (type) {
    case 'date':
    case 'month':
      return value;
    case 'datetime-local':
      return value.length === 16 ? value + ':00' : value; // Convert yyyy-MM-ddTHH:mm to yyyy-MM-ddTHH:mm:00
    case 'time':
      return value.length === 5 ? value + ':00' : value; // Convert hh:mm to hh:mm:00
    case 'week':
      // For now we are not going to normalize input type week as it is not trivial
      return value;
  }

  throw new Error(`Invalid element type '${type}'.`);
}

// The following interfaces must be kept in sync with the EventArgs C# classes

interface ChangeEventArgs {
  value: string | boolean | string[];
}

interface DragEventArgs {
  detail: number;
  dataTransfer: DataTransferEventArgs | null;
  screenX: number;
  screenY: number;
  clientX: number;
  clientY: number;
  button: number;
  buttons: number;
  ctrlKey: boolean;
  shiftKey: boolean;
  altKey: boolean;
  metaKey: boolean;
}

interface DataTransferEventArgs {
  dropEffect: string;
  effectAllowed: string;
  files: readonly string[];
  items: readonly DataTransferItem[];
  types: readonly string[];
}

interface DataTransferItem {
  kind: string;
  type: string;
}

interface ErrorEventArgs {
  message: string;
  filename: string;
  lineno: number;
  colno: number;
  type: string;

  // omitting 'error' here since we'd have to serialize it, and it's not clear we will want to
  // do that. https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent
}

interface KeyboardEventArgs {
  key: string;
  code: string;
  location: number;
  repeat: boolean;
  ctrlKey: boolean;
  shiftKey: boolean;
  altKey: boolean;
  metaKey: boolean;
  type: string;
}

interface MouseEventArgs {
  detail: number;
  screenX: number;
  screenY: number;
  clientX: number;
  clientY: number;
  offsetX: number;
  offsetY: number;
  pageX: number;
  pageY: number;
  movementX: number;
  movementY: number;
  button: number;
  buttons: number;
  ctrlKey: boolean;
  shiftKey: boolean;
  altKey: boolean;
  metaKey: boolean;
  type: string;
}

interface PointerEventArgs extends MouseEventArgs {
  pointerId: number;
  width: number;
  height: number;
  pressure: number;
  tiltX: number;
  tiltY: number;
  pointerType: string;
  isPrimary: boolean;
}

interface ProgressEventArgs {
  lengthComputable: boolean;
  loaded: number;
  total: number;
  type: string;
}

interface TouchEventArgs {
  detail: number;
  touches: TouchPoint[];
  targetTouches: TouchPoint[];
  changedTouches: TouchPoint[];
  ctrlKey: boolean;
  shiftKey: boolean;
  altKey: boolean;
  metaKey: boolean;
  type: string;
}

interface TouchPoint {
  identifier: number;
  screenX: number;
  screenY: number;
  clientX: number;
  clientY: number;
  pageX: number;
  pageY: number;
}

interface WheelEventArgs extends MouseEventArgs {
  deltaX: number;
  deltaY: number;
  deltaZ: number;
  deltaMode: number;
}

interface FocusEventArgs {
  type: string;
}

interface ClipboardEventArgs {
  type: string;
}