text:
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.tabmodel;

import androidx.annotation.Nullable;

import org.chromium.base.ObserverList;
import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabCreationState;
import org.chromium.chrome.browser.tab.TabLaunchType;
import org.chromium.chrome.browser.tab.TabSelectionType;
import org.chromium.content_public.browser.LoadUrlParams;

import java.util.ArrayList;
import java.util.List;

/**
 * Implement methods shared across the different model implementations.
 */
public abstract class TabModelSelectorBase
        implements TabModelSelector, IncognitoTabModelObserver, TabModelDelegate {
    private static final int MODEL_NOT_FOUND = -1;

    private static TabModelSelectorObserver sObserver;

    private List<TabModel> mTabModels = new ArrayList<>();
    private IncognitoTabModel mIncognitoTabModel;

    /**
     * This is a dummy implementation intended to stub out TabModelFilterProvider before native is
     * ready.
     */
    private TabModelFilterProvider mTabModelFilterProvider = new TabModelFilterProvider();

    private final TabModelFilterFactory mTabModelFilterFactory;
    private int mActiveModelIndex;

    private final ObserverList<TabModelSelectorObserver> mObservers = new ObserverList<>();
    private final ObserverList<IncognitoTabModelObserver> mIncognitoObservers =
            new ObserverList<>();

    @Nullable
    protected IncognitoReauthDialogDelegate mIncognitoReauthDialogDelegate;

    private boolean mTabStateInitialized;
    private boolean mStartIncognito;
    private boolean mReparentingInProgress;

    private final TabCreatorManager mTabCreatorManager;

    protected TabModelSelectorBase(TabCreatorManager tabCreatorManager,
            TabModelFilterFactory tabModelFilterFactory, boolean startIncognito) {
        mTabCreatorManager = tabCreatorManager;
        mTabModelFilterFactory = tabModelFilterFactory;
        mStartIncognito = startIncognito;
    }

    protected final void initialize(TabModel normalModel, IncognitoTabModel incognitoModel) {
        // Only normal and incognito supported for now.
        assert mTabModels.isEmpty();

        mTabModels.add(normalModel);
        mTabModels.add(incognitoModel);
        mIncognitoTabModel = incognitoModel;
        mActiveModelIndex = getModelIndex(mStartIncognito);
        assert mActiveModelIndex != MODEL_NOT_FOUND;
        mTabModelFilterProvider.init(mTabModelFilterFactory, mTabModels);
        addObserver(mTabModelFilterProvider);

        TabModelObserver tabModelObserver = new TabModelObserver() {
            @Override
            public void didAddTab(
                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
                notifyChanged();
                notifyNewTabCreated(tab, creationState);
            }

            @Override
            public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
                notifyChanged();
            }

            @Override
            public void didMoveTab(Tab tab, int newIndex, int curIndex) {
                notifyChanged();
            }
        };

        mTabModelFilterProvider.addTabModelFilterObserver(tabModelObserver);

        if (sObserver != null) {
            addObserver(sObserver);
        }

        mIncognitoTabModel.addIncognitoObserver(this);

        incognitoModel.setActive(mStartIncognito);
        normalModel.setActive(!mStartIncognito);

        notifyChanged();
    }

    public static void setObserverForTests(TabModelSelectorObserver observer) {
        sObserver = observer;
    }

    /**
     * Should be called once the native library is loaded so that the actual internals of this
     * class can be initialized.
     *
     * @param tabContentProvider A {@link TabContentManager} instance.
     */
    public void onNativeLibraryReady(TabContentManager tabContentProvider) {}

    @Override
    public void onTabsViewShown() {}

    @Override
    public void selectModel(boolean incognito) {
        if (mTabModels.size() == 0) {
            mStartIncognito = incognito;
            return;
        }
        int newIndex = getModelIndex(incognito);
        assert newIndex != MODEL_NOT_FOUND;
        if (newIndex == mActiveModelIndex) return;

        TabModel newModel = mTabModels.get(newIndex);
        TabModel previousModel = mTabModels.get(mActiveModelIndex);
        previousModel.setActive(false);
        newModel.setActive(true);
        mActiveModelIndex = newIndex;

        // Notify the re-auth code first so we show the re-auth dialog first.
        if (mIncognitoReauthDialogDelegate != null && newModel.isIncognito()) {
            mIncognitoReauthDialogDelegate.onBeforeIncognitoTabModelSelected();
        }

        for (TabModelSelectorObserver listener : mObservers) {
            listener.onTabModelSelected(newModel, previousModel);
        }
    }

    @Override
    public Tab getCurrentTab() {
        return TabModelUtils.getCurrentTab(getCurrentModel());
    }

    @Override
    public int getCurrentTabId() {
        Tab tab = getCurrentTab();
        return tab != null ? tab.getId() : Tab.INVALID_TAB_ID;
    }

    @Override
    public TabModel getModelForTabId(int id) {
        for (int i = 0; i < mTabModels.size(); i++) {
            TabModel model = mTabModels.get(i);
            if (TabModelUtils.getTabById(model, id) != null || model.isClosurePending(id)) {
                return model;
            }
        }
        return null;
    }

    @Override
    public TabModel getCurrentModel() {
        if (mTabModels.size() == 0) return EmptyTabModel.getInstance();
        return mTabModels.get(mActiveModelIndex);
    }

    @Override
    public int getCurrentModelIndex() {
        return mActiveModelIndex;
    }

    @Override
    public TabModel getModel(boolean incognito) {
        int index = getModelIndex(incognito);
        if (index == MODEL_NOT_FOUND) return EmptyTabModel.getInstance();
        return mTabModels.get(index);
    }

    private int getModelIndex(boolean incognito) {
        for (int i = 0; i < mTabModels.size(); i++) {
            if (incognito == mTabModels.get(i).isIncognito()) return i;
        }
        return MODEL_NOT_FOUND;
    }

    @Override
    public TabModelFilterProvider getTabModelFilterProvider() {
        return mTabModelFilterProvider;
    }

    @Override
    public boolean isIncognitoSelected() {
        if (mTabModels.size() == 0) return mStartIncognito;
        return getCurrentModel().isIncognito();
    }

    @Override
    public List<TabModel> getModels() {
        return mTabModels;
    }

    @Override
    public Tab openNewTab(
            LoadUrlParams loadUrlParams, @TabLaunchType int type, Tab parent, boolean incognito) {
        return mTabCreatorManager.getTabCreator(incognito).createNewTab(
                loadUrlParams, type, parent);
    }

    @Override
    public boolean closeTab(Tab tab) {
        for (int i = 0; i < getModels().size(); i++) {
            TabModel model = mTabModels.get(i);
            if (model.indexOf(tab) >= 0) {
                return model.closeTab(tab);
            }
        }
        assert false : "Tried to close a tab that is not in any model!";
        return false;
    }

    @Override
    public void commitAllTabClosures() {
        for (int i = 0; i < mTabModels.size(); i++) {
            mTabModels.get(i).commitAllTabClosures();
        }
    }

    @Override
    public Tab getTabById(int id) {
        for (int i = 0; i < getModels().size(); i++) {
            Tab tab = TabModelUtils.getTabById(mTabModels.get(i), id);
            if (tab != null) return tab;
        }
        return null;
    }

    @Override
    public void closeAllTabs() {
        closeAllTabs(false);
    }

    @Override
    public void closeAllTabs(boolean uponExit) {
        for (int i = 0; i < getModels().size(); i++) {
            mTabModels.get(i).closeAllTabs(uponExit);
        }
    }

    @Override
    public int getTotalTabCount() {
        int count = 0;
        for (int i = 0; i < getModels().size(); i++)  {
            count += mTabModels.get(i).getCount();
        }
        return count;
    }

    @Override
    public void addObserver(TabModelSelectorObserver observer) {
        if (!mObservers.hasObserver(observer)) mObservers.addObserver(observer);
    }

    @Override
    public void removeObserver(TabModelSelectorObserver observer) {
        mObservers.removeObserver(observer);
    }

    /**
     * Marks the task state being initialized and notifies observers.
     */
    public void markTabStateInitialized() {
        if (mTabStateInitialized) return;
        mTabStateInitialized = true;
        for (TabModelSelectorObserver listener : mObservers) listener.onTabStateInitialized();
    }

    @Override
    public boolean isTabStateInitialized() {
        return mTabStateInitialized;
    }

    @Override
    public void destroy() {
        removeObserver(mTabModelFilterProvider);
        mTabModelFilterProvider.destroy();

        if (mIncognitoTabModel != null) {
            mIncognitoTabModel.removeIncognitoObserver(this);
        }
        for (int i = 0; i < getModels().size(); i++) mTabModels.get(i).destroy();
        mTabModels.clear();
    }

    /**
     * Notifies all the listeners that the {@link TabModelSelector} or its {@link TabModel} has
     * changed.
     */
    // TODO(tedchoc): Remove the need for this to be exposed.
    public void notifyChanged() {
        for (TabModelSelectorObserver listener : mObservers) {
            listener.onChange();
        }
    }

    /**
     * Notifies all the listeners that a new tab has been created.
     * @param tab The tab that has been created.
     * @param creationState How the tab was created.
     */
    private void notifyNewTabCreated(Tab tab, @TabCreationState int creationState) {
        for (TabModelSelectorObserver listener : mObservers) {
            listener.onNewTabCreated(tab, creationState);
        }
    }

    /**
     * Notifies all the listeners that a tab has been hidden to switch to another.
     * @param tab The tab that has been hidden.
     */
    protected void notifyTabHidden(Tab tab) {
        for (TabModelSelectorObserver listener : mObservers) {
            listener.onTabHidden(tab);
        }
    }

    protected TabCreatorManager getTabCreatorManager() {
        return mTabCreatorManager;
    }

    @Override
    public void enterReparentingMode() {
        mReparentingInProgress = true;
    }

    @Override
    public boolean isReparentingInProgress() {
        return mReparentingInProgress;
    }

    @Override
    public void addIncognitoTabModelObserver(IncognitoTabModelObserver incognitoObserver) {
        mIncognitoObservers.addObserver(incognitoObserver);
    }

    @Override
    public void removeIncognitoTabModelObserver(IncognitoTabModelObserver incognitoObserver) {
        mIncognitoObservers.removeObserver(incognitoObserver);
    }

    @Override
    public void wasFirstTabCreated() {
        for (IncognitoTabModelObserver observer : mIncognitoObservers) {
            observer.wasFirstTabCreated();
        }
    }

    @Override
    public void didBecomeEmpty() {
        for (IncognitoTabModelObserver observer : mIncognitoObservers) {
            observer.didBecomeEmpty();
        }
    }

    @Override
    public void setIncognitoReauthDialogDelegate(
            IncognitoReauthDialogDelegate incognitoReauthDialogDelegate) {
        mIncognitoReauthDialogDelegate = incognitoReauthDialogDelegate;
    }
}


text:
Professional blog: [cmakara.github.io](http://cmakara.github.io)

## License

MIT License

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

        Shipment ID
        Container Qty

                    Railway Origination
                    Railway Destination
                    Container No.
                    Fleet
                    Plate No.
                    Trucker
                    Loading TOC
                    Trans Plan No.
                    Rail ETS
                    Station TOA
                    Rail ATS

                    Railway Origination
                    Railway Destination

                        Container No.

                    Trucker
                    Container No.
                    Trucker
                    Loading TOC
                    Trans Plan No.
                    Rail TOA
                    Station TOA
                    Rail ATS

                    Barge Origination
                    Barge Destination
                    SP Name
                    Container No.
                    BOL No.
                    Barge SLOT
                    Barge ETS

                    Barge Origination
                    Barge Destination
                    SP Name

                        Container No.

                    BOL No.
                    Slot
                    Barge ETS

                    Vessel Origination
                    Vessel Destination
                    SP Name
                    Container No.
                    BOL No.
                    Vessel SLOT
                    Vessel ETS

                    Vessel Origination
                    Vessel Destination
                    SP Name

                        Container No.

                    BOL No.
                    Slot
                    Vessel ETS


text:
layout: post-index
title: Tous les articles de ZOL
excerpt: "Liste de tous les articles techniques de ZOL"
---


text:
package com.weisong.test.comm.transport.routing;

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

abstract public class CBaseRoute implements CRoute {

	private List<CRouteSelector> selectors = new LinkedList<>();

	public CBaseRoute(CRouteSelector ... array) {
		for(CRouteSelector s : array) {
			selectors.add(s);
		}
	}

	public CRoute addRouteSelector(CRouteSelector s) {
		this.selectors.add(s);
		return this;
	}

	@Override
	public boolean isSelected(String address) {
		for(CRouteSelector s : selectors) {
			if(s.isSelected(address)) {
				return true;
			}
		}
		return false;
	}
}


text:
package _07FoodShortage;

public interface Buyer {
    void buyFood();
    int getFood();
}


text:
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace TestBindings
{
    public partial class TestBindingsViewController : UIViewController
    {
        public TestBindingsViewController() : base ("TestBindingsViewController", null)
        {
        }

        public override void DidReceiveMemoryWarning()
        {
            // Releases the view if it doesn't have a superview.
            base.DidReceiveMemoryWarning();

            // Release any cached data, images, etc that aren't in use.
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Perform any additional setup after loading the view, typically from a nib.
        }

        public override bool ShouldAutorotateToInterfaceOrientation(UIInterfaceOrientation toInterfaceOrientation)
        {
            // Return true for supported orientations
            return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
        }
    }
}


text:
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/cloud/contactcenterinsights/v1/contact_center_insights.proto

package com.google.cloud.contactcenterinsights.v1;

public interface GetIssueRequestOrBuilder
    extends
    // @@protoc_insertion_point(interface_extends:google.cloud.contactcenterinsights.v1.GetIssueRequest)
    com.google.protobuf.MessageOrBuilder {

  /**
   *
   *
   *

   * Required. The name of the issue to get.
   *

   *
   *
   * string name = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
   *
   *
   * @return The name.
   */
  java.lang.String getName();
  /**
   *
   *
   *

   * Required. The name of the issue to get.
   *

   *
   *
   * string name = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
   *
   *
   * @return The bytes for name.
   */
  com.google.protobuf.ByteString getNameBytes();
}


text:
{% extends '_base.html' %}

{% block head_title %}Profile - {{ block.super }}{% endblock %}

{% comment %}
At some point, we may end up needing to branch the profile page template
in order to support data available for different releases. And we may end up
with a special template for subtopic pages within a profile. This page provides
a profile-specific base suitable for applying things across that entire
family of pages.
{% endcomment %}


text:
package org.adligo.tests4j.system.shared.api;

import org.adligo.tests4j.shared.common.StringMethods;
import org.adligo.tests4j.shared.i18n.I_Tests4J_Constants;
import org.adligo.tests4j.shared.i18n.I_Tests4J_ParamsReaderMessages;
import org.adligo.tests4j.shared.xml.I_XML_Builder;
import org.adligo.tests4j.shared.xml.XML_Parser;

/**
 *  a immutable implementation of I_Tests4J_RemoteInfo,
 *  used to tell test4j where remote tests4j instances are
 *  so they can be called/delegated to.
 *
 * @author scott
 *
 */
public class Tests4J_RemoteInfo implements I_Tests4J_RemoteInfo {

	private final I_Tests4J_ParamsReaderMessages messages_;
	private String host;
	private int port;
	private String authCode;

	protected Tests4J_RemoteInfo(I_Tests4J_Constants constants) {
	  messages_ = constants.getParamReaderMessages();
	}

	public Tests4J_RemoteInfo(I_Tests4J_Constants constants, I_Tests4J_RemoteInfo other) {
		this(constants, other.getHost(), other.getPort(), other.getAuthCode());
	}

	/**
	 * Validates that there is something in the authCode field, by
	 * the end of the constructor.  This is done to make Tests4J_ParamsReader
	 * simpler, by delegating logic.
	 *
	 * @param other
	 * @param defaultAuthCode
	 */
	public Tests4J_RemoteInfo(I_Tests4J_Constants constants, I_Tests4J_RemoteInfo other, String defaultAuthCode) {
		this(constants, other);
		if (authCode == null) {
			authCode = defaultAuthCode;
		}
		if (StringMethods.isEmpty(authCode)) {
			throw new IllegalArgumentException(messages_.getAuthCodeOrAuthCodeDefaultRequired());
		}
	}

	public Tests4J_RemoteInfo(I_Tests4J_Constants constants, String pHost, int pPort, String pAuthCode) {
	  messages_ = constants.getParamReaderMessages();
		if (StringMethods.isEmpty(pHost)) {
			throw new IllegalArgumentException(messages_.getHostRequired());
		}
		host = pHost;
		port = pPort;
		//auth code can be empty or null, until the Tests4J_Params reader,
		//at which point it must either come from the I_Tests4J_Params instance or
		// this
		authCode = pAuthCode;
	}

	/* (non-Javadoc)
	 * @see org.adligo.tests4j.models.shared.system.I_Tests4J_RemoteInfo#getHost()
	 */
	@Override
	public String getHost() {
		return host;
	}
	/* (non-Javadoc)
	 * @see org.adligo.tests4j.models.shared.system.I_Tests4J_RemoteInfo#getPort()
	 */
	@Override
	public int getPort() {
		return port;
	}
	/* (non-Javadoc)
	 * @see org.adligo.tests4j.models.shared.system.I_Tests4J_RemoteInfo#getAuthCode()
	 */
	@Override
	public String getAuthCode() {
		return authCode;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((authCode == null) ? 0 : authCode.hashCode());
		result = prime * result + ((host == null) ? 0 : host.hashCode());
		result = prime * result + port;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Tests4J_RemoteInfo other = (Tests4J_RemoteInfo) obj;
		if (authCode == null) {
			if (other.authCode != null)
				return false;
		} else if (!authCode.equals(other.authCode))
			return false;
		if (host == null) {
			if (other.host != null)
				return false;
		} else if (!host.equals(other.host))
			return false;
		if (port != other.port)
			return false;
		return true;
	}

	@Override
	public void toXml(I_XML_Builder builder) {
		builder.indent();
		int attribsPerLine = builder.getAttributesPerLine();
		builder.setAttributesPerLine(4);
		builder.addStartTag(TAG_NAME);
		builder.addAttribute(HOST_ATTRIBUTE, host);
		builder.addAttribute(PORT_ATTRIBUTE, "" + port);
		if ( !StringMethods.isEmpty(authCode)) {
			builder.addAttribute(AUTH_ATTRIBUTE, authCode);
		}
		builder.setAttributesPerLine(attribsPerLine);
		builder.append(" />");
		builder.endLine();
	}

}


text:
package org.olat.test.util.setup.context;

import java.io.File;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import junit.framework.AssertionFailedError;

import org.olat.test.util.selenium.OlatLoginHelper;
import org.olat.test.util.selenium.SeleniumManager;
import org.olat.test.util.selenium.olatapi.OLATWorkflowHelper;
import org.olat.test.util.selenium.olatapi.WorkflowHelper;
import org.olat.test.util.setup.OlatLoginInfos;
import org.olat.test.util.setup.SetupType;
import org.olat.testutils.codepoints.client.CodepointClient;
import org.olat.testutils.codepoints.client.CodepointRef;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.thoughtworks.selenium.Selenium;

/**
 * Setups the context for running selenium tests.

 * Configurable via customcontext.xml if any available, else via defaultcontext.xml
 *
 * @author eglis
 *
 */
public abstract class Context {

    public static InheritableThreadLocal<Context> currentContext = new InheritableThreadLocal<Context>();

    private static Map<SetupType, Context> contexts_;
    protected final static String log4JConfigFilenameKey = "log4jConfigFilename";
    protected boolean cleanupBeforeTest = true; // should be read from context?
    public static String FILE_RESOURCES_PATH = "org/olat/test/file_resources/";
    public static String DEMO_COURSE_NAME_1 = "OLAT: Demo course";
    public static String DEMO_COURSE_NAME_2 = "OLAT: Demo course";
    public static String DEMO_COURSE_NAME_3 = "OLAT: Demokurs Einschreibung";

    static {
        System.out.println(new Date());
        System.out.println("INITIALIZING SPRING WITH contexts.xml FOR SELENIUMTESTS' CONTEXT...");
        contexts_ = new HashMap<SetupType, Context>();
        new ClassPathXmlApplicationContext(new String[] { "classpath*:customcontext.xml" });
        if (contexts_.size() == 0) {
            new ClassPathXmlApplicationContext(new String[] { "classpath*:defaultcontext.xml" });
        }
        System.out.println("DONE.");
    }

    /**
     * The SeleniumManager is used for creating and closing Selenium instances. The abstract Context base class sets up this instance before the Context is used for
     * creating selenium instances the first time.
     */
    protected SeleniumManager seleniumManager_;

    private List<CodepointClient> codepointClients_ = new LinkedList<CodepointClient>();;

    private Map<String, String> config_ = new HashMap<String, String>();

    private SetupType setupType_;

    protected void initContext() {
        SetupType[] setupTypes = SetupType.values();
        for (int i = 0; i < setupTypes.length; i++) {
            SetupType setupType = setupTypes[i];
            if (supportsSetupType(setupType)) {
                if (contexts_.containsKey(setupType)) {
                    throw new IllegalArgumentException("There is already a Context defined for SetupType " + setupType.name());
                }
                contexts_.put(setupType, this);
            }
        }
        setConfigProperty("browserId", "*chrome");
    }

    protected abstract boolean supportsSetupType(SetupType setupType);

    private static Context getContext(SetupType setupType) {
        Context c = contexts_.get(setupType);
        if (c == null) {
            throw new IllegalStateException("No Context found for SetupType " + setupType.name());
        }
        return c;
    }

    public SetupType getSetupType() {
        return setupType_;
    }

    public boolean isSingleVMSetupType() {
        return getSetupType().isSingleVm();
    }

    public void setConfig(Map<String, String> config) {
        Iterator<Map.Entry<String, String>> it = config.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String> entry = it.next();
            config_.put(entry.getKey(), entry.getValue());
        }
    }

    public String getConfigProperty(String key) {
        if (config_ == null) {
            throw new IllegalStateException("config_ must not be null.");
        }
        return config_.get(key);
    }

    public void setConfigProperty(String key, String value) {
        if (config_ == null) {
            throw new IllegalStateException("config_ must not be null.");
        }
        config_.put(key, value);
    }

    public static Context setupContext(String testName, SetupType setupType) {
        if (currentContext.get() != null) {
            throw new IllegalStateException("Context is already setup. You must do a context.tearDown() first before doing another Context.setupContext Mate!");
        }
        Context c = getContext(setupType);
        if (c == null) {
            throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly?");
        }
        currentContext.set(c);
        System.out.println("============================");
        System.out.println("Context.setupContext   START(" + testName + "," + setupType.name() + ")");
        System.out.println("seleniumHost     = " + c.getConfigProperty("seleniumHost"));
        System.out.println("browserId        = " + c.getConfigProperty("browserId"));
        System.out.println("withCodepoints     = " + c.getConfigProperty("withCodepoints"));
        System.out.println("jmsBrokerUrl     = " + c.getConfigProperty("jmsBrokerUrl"));
        System.out.println("instanceId       = " + c.getConfigProperty("instanceId"));

        if (setupType.isSingleVm()) {
            // then we have exactly 1 url
            System.out.println("singleVmOlatUrl  = " + c.getConfigProperty("singleVmOlatUrl"));
        } else {
            // then we have multiple. unclear how many, so lets just loop
            int nodeId = 1;
            while (c.getConfigProperty("multiVmOlatUrl" + nodeId) != null) {
                System.out.println("multiVmOlatUrl" + nodeId + "  = " + c.getConfigProperty("multiVmOlatUrl" + nodeId));
                nodeId++;
            }
        }
        System.out.println("admin            = " + c.getConfigProperty("adminUsername") + "/" + c.getConfigProperty("adminPassword"));
        System.out.println("author           = " + c.getConfigProperty("authorUsername") + "/" + c.getConfigProperty("authorPassword"));
        System.out.println("student          = " + c.getConfigProperty("studentUsername") + "/" + c.getConfigProperty("studentPassword"));
        System.out.println("guest            = " + c.getConfigProperty("guestUsername") + "/" + c.getConfigProperty("guestPassword"));
        // ............
        System.out.println("log4JConfigFilename = " + c.getConfigProperty(log4JConfigFilenameKey));

        c.seleniumManager_ = new SeleniumManager(testName);
        c.setupType_ = setupType;
        c.doSetupContext(setupType);

        System.out.println("Context.setupContext     END(" + testName + "," + setupType.name() + ")");
        System.out.println("============================");
        // and return the context itself
        return c;
    }

    public static Context getContext() {
        Context c = currentContext.get();
        if (c == null) {
            throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly? And, did you call Context.setupContext() ?");
        }
        return c;
    }

    /**
     * Try to find out if it is a KnownIssueException somewhere in the olat.log - and if so, don't report it as the original failure but as a known issue so we
     * immediately know from the test result that it is a known issue.

     * Returns by default false, that is "Do not mask the test failure if ERROR encountered in olat.log".

     * It never returns true, but it throws a AssertionFailedError if a "Known Issue" encountered.
     *
     * @param th
     * @return
     * @throws Exception
     */
    public static boolean maskTestFailureOrError(Throwable th) throws Exception {
        Context c = currentContext.get();
        if (c == null) {
            throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly? And, did you call Context.setupContext() ?");
        }
        if (c.doMaskTestFailureOrError(th)) {
            return true;
        }
        if (th.getMessage().contains("INST-MSG-author")) {
            throw new AssertionFailedError("Known Issue 3841 encountered.");
        }
        if (c.seleniumManager_.anySeleniumBrowserHasKnownIssue3857()) {
            throw new AssertionFailedError(
                    "Known Issue 3857 encountered. (\"Please do not use the `Reload` or `Back` button of your browser.\" encountered in one of the browsers)");
        }
        return false;
    }

    protected boolean doMaskTestFailureOrError(Throwable th) throws Exception {
        return false;
    }

    public static void tearDown() {
        System.out.println("======== TEARDOWNSTART =====");
        try {
            staticDoTearDown();
        } catch (Error er) {
            er.printStackTrace(System.out);
            throw er;
        } catch (RuntimeException re) {
            re.printStackTrace(System.out);
            throw re;
        } finally {
            System.out.println("======= TEARDOWNFINALLY ====");
        }
    }

    private final static void staticDoTearDown() {
        Context c = currentContext.get();
        if (c == null) {
            throw new IllegalStateException("Context not configured. contexts.xml in classpath and configured correctly? And, did you call Context.setupContext() ?");
        }
        System.out.println("============================");
        System.out.println("Context.tearDown()     START");

        c.doTearDown();

        System.out.println("----------------------------");
        System.out.println("Closing CodepointClients....");
        int cnt = 0;
        for (Iterator<CodepointClient> it = c.codepointClients_.iterator(); it.hasNext();) {
            System.out.println("CodepointClient[" + cnt + "] START");
            CodepointClient codepointClient = it.next();
            try {
                System.out.println("CodepointClient[" + cnt + "] fetching all codepoints for debug...");
                List<CodepointRef> codepoints = codepointClient.listAllCodepoints();
                System.out.println("CodepointClient[" + cnt + "] going through all codepoints now...");
                for (Iterator<CodepointRef> it2 = codepoints.iterator(); it2.hasNext();) {
                    CodepointRef codepointRef = it2.next();
                    System.out.println("[Codepoint-" + codepointClient + "]: " + codepointRef.getId() + ", hitCount=" + codepointRef.getHitCount());
                }
                System.out.println("CodepointClient[" + cnt + "] done with going through all codepoints.");
            } catch (AssertionError ae) {
                // ok, be silent here
            } catch (Exception e) {
                System.out.println("Exception in list codepoint: " + e);
                e.printStackTrace(System.out);
            }
            System.out.println("CodepointClient[" + cnt + "] closing codepointclient now...");
            codepointClient.close();
            System.out.println("CodepointClient[" + cnt + "] END");
            cnt++;
        }
        System.out.println("Closed CodepointClients.");
        System.out.println("----------------------------");

        currentContext.set(null);

        System.out.println("Context.tearDown()       END");
        System.out.println("============================");
    }

    protected abstract void doSetupContext(SetupType setupType);

    protected abstract void doTearDown();

    /**
     * public void deleteAllLearningResourcesFromMyAuthors() { WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardAdminOlatLoginInfos(1).getUsername());
     * WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardAuthorOlatLoginInfos(1).getUsername());
     * WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardStudentOlatLoginInfos(1).getUsername());
     * WorkflowHelper.deleteAllLearningResourcesFromAuthor(getStandardGuestOlatLoginInfos(1).getUsername()); }
     **/

    public Selenium createSelenium() {
        return createSelenium(getStandardAdminOlatLoginInfos(1));
    }

    public Selenium createSelenium(int nodeId) {
        return createSelenium(getStandardAdminOlatLoginInfos(nodeId));
    }

    public Selenium createSelenium(OlatLoginInfos loginInfos) {
        Selenium selenium = seleniumManager_.createSelenium(loginInfos);
        return selenium;
    }

    public Selenium createSeleniumAndLogin() {
        return createSeleniumAndLogin(getStandardAdminOlatLoginInfos(1));
    }

    public Selenium createSeleniumAndLogin(OlatLoginInfos loginInfos) {
        Selenium selenium = seleniumManager_.createSelenium(loginInfos);

        OlatLoginHelper.olatLogin(selenium, loginInfos);

        // make sure the login worked
        if (!"OLAT - Home".equals(selenium.getTitle())) {
            throw new AssertionError("createSeleniumAndLogin failed - expected to be logged in now and seeing 'OLAT - Home' - but instead I'm on this page: "
                    + selenium.getTitle());
        }
        return selenium;
    }

    /**
     * Creates selenium, login and return an OLAT abstraction instance.
     *
     * @param loginInfos
     * @return THE OLAT ABSTRACTION entry point
     */
    public OLATWorkflowHelper getOLATWorkflowHelper(OlatLoginInfos loginInfos) {
        Selenium selenium = seleniumManager_.createSelenium(loginInfos);

        OlatLoginHelper.olatLogin(selenium, loginInfos);

        // make sure the login worked
        if (!"OLAT - Home".equals(selenium.getTitle())) {
            throw new AssertionError("createSeleniumAndLogin failed - expected to be logged in now and seeing 'OLAT - Home' - but instead I'm on this page: "
                    + selenium.getTitle());
        }
        return new OLATWorkflowHelper(selenium);
    }

    /**
     * Create user
     *
     * @param nodeId
     * @param username
     * @param password
     * @param isSystemUser
     * @param userManagementRole
     * @param groupManagementRole
     * @param authorRole
     * @param systemAdminRole
     * @return
     */
    public OlatLoginInfos createuserIfNotExists(int nodeId, String username, String password, boolean isSystemUser, boolean userManagementRole,
            boolean groupManagementRole, boolean authorRole, boolean systemAdminRole) {

        try {
            return WorkflowHelper.createUserIfNotExists(getStandardAdminOlatLoginInfos(nodeId), username, password, isSystemUser, userManagementRole,
                    groupManagementRole, authorRole, systemAdminRole);
        } catch (InterruptedException e) {
            e.printStackTrace(System.out);
            throw new RuntimeException(e);
        }
    }

    /**
     * Create user by login as admin with the given name and the standard password.
     *
     * @param nodeId
     * @param username
     * @param isSystemUser
     * @param userManagementRole
     * @param groupManagementRole
     * @param authorRole
     * @param systemAdminRole
     * @return
     */
    public OlatLoginInfos createuserIfNotExists(int nodeId, String username, boolean isSystemUser, boolean userManagementRole, boolean groupManagementRole,
            boolean authorRole, boolean systemAdminRole) {
        return createuserIfNotExists(nodeId, username, getStandardPassword(), isSystemUser, userManagementRole, groupManagementRole, authorRole, systemAdminRole);
    }

    public CodepointClient createCodepointClient(int nodeId) {
        CodepointClient codepointClient;
        try {
            codepointClient = doCreateCodepointClient(nodeId);
        } catch (Exception e) {
            e.printStackTrace(System.out);
            throw new RuntimeException(e);
        }
        codepointClients_.add(codepointClient);
        return codepointClient;
    }

    /**
     * Creates a codepoint client for the server node with the given id.
     *
     * @param nodeId
     * @return
     * @throws Exception
     */
    protected abstract CodepointClient doCreateCodepointClient(int nodeId) throws Exception;

    public OlatLoginInfos getStandardAdminOlatLoginInfos() {
        if (!isSingleVMSetupType()) {
            throw new IllegalStateException("In Cluster mode you need to specify the nodeId of this login");
        }
        return getStandardAdminOlatLoginInfos(1);
    }

    public OlatLoginInfos getStandardAuthorOlatLoginInfos() {
        if (!isSingleVMSetupType()) {
            throw new IllegalStateException("In Cluster mode you need to specify the nodeId of this login");
        }
        return getStandardAuthorOlatLoginInfos(1);
    }

    public OlatLoginInfos getStandardStudentOlatLoginInfos() {
        return getStandardStudentOlatLoginInfos(1);
    }

    public OlatLoginInfos getStandardGuestOlatLoginInfos() {
        return getStandardGuestOlatLoginInfos(1);
    }

    public OlatLoginInfos getStandardAdminOlatLoginInfos(int nodeId) {
        return createLoginInfos(nodeId, getConfigProperty("adminUsername"), getConfigProperty("adminPassword"));
    }

    public OlatLoginInfos getStandardAuthorOlatLoginInfos(int nodeId) {
        return createLoginInfos(nodeId, getConfigProperty("authorUsername"), getConfigProperty("authorPassword"));
    }

    public OlatLoginInfos getStandardStudentOlatLoginInfos(int nodeId) {
        return createLoginInfos(nodeId, getConfigProperty("studentUsername"), getConfigProperty("studentPassword"));
    }

    public OlatLoginInfos getStandardGuestOlatLoginInfos(int nodeId) {
        return createLoginInfos(nodeId, getConfigProperty("guestUsername"), getConfigProperty("guestPassword"));
    }

    protected String getOlatUrl(int nodeId) {
        if (isSingleVMSetupType()) {
            if (nodeId != 1) {
                throw new IllegalArgumentException("Cannot refer to nodeId other than 1 while having SetupType set to SINGLE VM");
            }
            return getConfigProperty("singleVmOlatUrl");
        } else {
            return getConfigProperty("multiVmOlatUrl" + nodeId);
        }
    }

    protected OlatLoginInfos createLoginInfos(int nodeId, String username, String password) {
        String olatUrl = getOlatUrl(nodeId);
        try {
            return new OlatLoginInfos(getConfigProperty("seleniumHost"), getConfigProperty("browserId"), olatUrl, username, password);
        } catch (MalformedURLException e) {
            throw new RuntimeException("MalformedURLException (" + olatUrl + ") when creating admin login infos: " + e);
        }
    }

    /**
     * Beware: this does not check if the user data is valid!!!
     *
     * @param nodeId
     * @param username
     * @param password
     * @return Returns an OlatLoginInfos for the username, password, and nodeId.
     */
    public OlatLoginInfos getOlatLoginInfo(int nodeId, String username, String password) {
        // TODO:LD: see is user data check needed (e.g. admin login and check if username exists and change password to the given one)
        return createLoginInfos(nodeId, username, password);
    }

    /**
     * Creates a OlatLoginInfos object using the context info and the standard password.
     *
     * @param nodeId
     * @param username
     * @return
     */
    public OlatLoginInfos getOlatLoginInfo(int nodeId, String username) {
        // TODO:LD: see is user data check needed (e.g. admin login and check if username exists and change password to the given one)
        return createLoginInfos(nodeId, username, getStandardStudentOlatLoginInfos(1).getPassword());
    }

    /**
     * Convention: all test users could use a standard password, and we assume that this is the default student password.
     *
     * @return
     */
    private String getStandardPassword() {
        return getStandardStudentOlatLoginInfos(1).getPassword();
    }

    /**
     * Copies the localFile to the seleniumHost location.
     *
     * @param localFile
     * @return
     */
    public abstract String provideFileRemotely(File localFile);

    /**
     * Restarts Selenium RC server.
     *
     * @throws AssertionError
     */
    protected abstract void restartSeleniumServer() throws AssertionError;

}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Square_Area
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("a = ");
            int a = int.Parse(Console.ReadLine());
            int square = a * a;
            Console.WriteLine("Square = "+square);
        }
    }
}


text:
/**
 * This class was created by <Vazkii>. It's distributed as
 * part of the Botania Mod. Get the Source Code in github:
 * https://github.com/Vazkii/Botania
 *
 * Botania is Open Source and distributed under a
 * Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License
 * (http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB)
 *
 * File Created @ [Jan 16, 2014, 4:52:06 PM (GMT)]
 */
package pixlepix.reactors.lexicon.button;

import net.minecraft.client.Minecraft;
import net.minecraft.util.StatCollector;
import org.lwjgl.opengl.GL11;
import pixlepix.reactors.lexicon.GuiLexicon;
import pixlepix.reactors.lexicon.VazkiiRenderHelper;

import java.util.Arrays;

public class GuiButtonPage extends GuiButtonLexicon {

    boolean right;

    public GuiButtonPage(int par1, int par2, int par3, boolean right) {
        super(par1, par2, par3, 18, 10, "");
        this.right = right;
    }

    @Override
    public void drawButton(Minecraft par1Minecraft, int par2, int par3) {
        if (enabled) {
            field_146123_n = par2 >= xPosition && par3 >= yPosition && par2 < xPosition + width && par3 < yPosition + height;
            int k = getHoverState(field_146123_n);

            par1Minecraft.renderEngine.bindTexture(GuiLexicon.texture);
            GL11.glColor4f(1F, 1F, 1F, 1F);
            drawTexturedModalRect(xPosition, yPosition, k == 2 ? 18 : 0, right ? 180 : 190, 18, 10);

            if (k == 2)
                VazkiiRenderHelper.renderTooltip(par2, par3, Arrays.asList(StatCollector.translateToLocal(right ? "auramisc.nextPage" : "auramisc.prevPage")));
        }
    }

}


text:
from numpy.random import rand, randint
from matplotlib.patches import RegularPolygon
import matplotlib.pyplot as plt
import numpy as np

class PatchMover(object):
    def __init__(self, ax):
        self.ax = ax
        self.selected_patch = None
        self.start_mouse_pos = None
        self.start_patch_pos = None

        fig = ax.figure
        fig.canvas.mpl_connect('button_press_event', self.on_press)
        fig.canvas.mpl_connect('button_release_event', self.on_release)
        fig.canvas.mpl_connect('motion_notify_event', self.on_motion)

    def on_press(self, event):
        for patch in reversed(self.ax.patches):
            if patch.contains_point((event.x, event.y)):
                self.selected_patch = patch
                self.start_mouse_pos = np.array([event.xdata, event.ydata])
                self.start_patch_pos = patch.xy
                break

    def on_motion(self, event):
        if self.selected_patch is not None:
            pos = np.array([event.xdata, event.ydata])
            self.selected_patch.xy = self.start_patch_pos + pos - self.start_mouse_pos
            self.ax.figure.canvas.draw()

    def on_release(self, event):
        self.selected_patch = None

fig, ax = plt.subplots()
ax.set_aspect("equal")
for i in range(10):
    poly = RegularPolygon(rand(2), randint(3, 10), rand()*0.1+0.1, facecolor=rand(3))
    ax.add_patch(poly)
ax.relim()
ax.autoscale()
pm = PatchMover(ax)
plt.show()


text:
// Copyright (c) 2012 Ecma International.  All rights reserved.
// Ecma International makes this code available under the terms and conditions set
// forth on http://hg.ecmascript.org/tests/test262/raw-file/tip/LICENSE (the
// "Use Terms").   Any redistribution of this code must retain the above
// copyright and this notice and otherwise comply with the Use Terms.

/*---
es5id: 15.4.4.17-5-1
description: Array.prototype.some - thisArg is passed
includes: [runTestCase.js]
---*/

function testcase() {
        this._15_4_4_17_5_1 = false;
        var _15_4_4_17_5_1 = true;

        function callbackfn(val, idx, obj) {
            return this._15_4_4_17_5_1;
        }
        var arr = [1];
        return !arr.some(callbackfn);
    }
runTestCase(testcase);


text:
using namespace std;

float getBuildingHeight() {
    float height;
    cout << "Please enter the height of the building (in meters): ";
    cin >> height;
    return height;
}

float getDistance(int t) {
    return (initVel * t) + ((gravity * (t * t)) / 2);
}

void printHeight(int t, float height) {
    cout << "At " << t << " seconds, the ball is at height: " << height << " meters" << endl;
}

int main() {
	float initHeight, currentHeight, dist;
    initHeight = getBuildingHeight();
    for (int t = 0; t <= numSecs; t++) {
        currentHeight = initHeight - getDistance(t);
        if (currentHeight > 0) {
            printHeight(t, currentHeight);
        }
        else {
            cout << "At " << t << " seconds, the ball is on the ground" << endl;
            break;
        }
    }
	return 0;
}


text:
@extends('enblogmaster')

@section('content')

                    <button class="mdl-button mdl-js-ripple-effect mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-color--accent">shopping_cart</button>

                        Rp. 10.000

                            TeaLinuxOS kit

                        <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
                            share
                        </button>

                    <button class="mdl-button mdl-js-ripple-effect mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-color--accent">shopping_cart</button>

                        Rp. 50.000

                            Mug TeaLinux

                        <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
                            share
                        </button>

                    <button class="mdl-button mdl-js-ripple-effect mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-color--accent">shopping_cart</button>

                        Rp. 100.000

                            Kaos TeaLinuxOS

                        <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
                            share
                        </button>

@endsection


text:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
using Ionic.Zip;
using Shimmer.Core;
using ReactiveUI;
using Shimmer.Tests.WiXUi;

namespace Shimmer.Tests.TestHelpers
{
    public static class IntegrationTestHelper
    {
        public static string GetPath(params string[] paths)
        {
            var ret = GetIntegrationTestRootDirectory();
            return (new FileInfo(paths.Aggregate (ret, Path.Combine))).FullName;
        }

        public static string GetIntegrationTestRootDirectory()
        {
            // XXX: This is an evil hack, but it's okay for a unit test
            // We can't use Assembly.Location because unit test runners love
            // to move stuff to temp directories
            var st = new StackFrame(true);
            var di = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(st.GetFileName()), ".."));

            return di.FullName;
        }

        public static bool SkipTestOnXPAndVista()
        {
            int osVersion = Environment.OSVersion.Version.Major*100 + Environment.OSVersion.Version.Minor;
            return (osVersion < 601);
        }

        public static void RunBlockAsSTA(Action block)
        {
            Exception ex = null;
            var t = new Thread(() => {
                try {
                    block();
                } catch (Exception e) {
                    ex = e;
                }
            });

            t.SetApartmentState(ApartmentState.STA);
            t.Start();
            t.Join();

            if (ex != null) {
                // NB: If we don't do this, the test silently passes
                throw new Exception("", ex);
            }
        }

        static object gate = 42;
        public static IDisposable WithFakeInstallDirectory(string packageFileName, out string path)
        {
            var ret = Utility.WithTempDirectory(out path);

            File.Copy(GetPath("fixtures", packageFileName), Path.Combine(path, packageFileName));
            var rp = ReleaseEntry.GenerateFromFile(Path.Combine(path, packageFileName));
            ReleaseEntry.WriteReleaseFile(new[] { rp }, Path.Combine(path, "RELEASES"));

            // NB: This is a temporary hack. The reason we serialize the tests
            // like this, is to make sure that we don't have two tests registering
            // their Service Locators with RxApp.
            Monitor.Enter(gate);
            return new CompositeDisposable(ret, Disposable.Create(() => Monitor.Exit(gate)));
        }

        public static IDisposable WithFakeInstallDirectory(out string path)
        {
            return WithFakeInstallDirectory("SampleUpdatingApp.1.1.0.0.nupkg", out path);
        }

        public static IDisposable WithFakeAlreadyInstalledApp(out string path)
        {
            return WithFakeAlreadyInstalledApp("InstalledSampleUpdatingApp-1.1.0.0.zip", out path);
        }

        public static IDisposable WithFakeAlreadyInstalledApp(string zipFile, out string path)
        {
            var ret = Utility.WithTempDirectory(out path);

            var zf = new ZipFile(GetPath("fixtures", zipFile));
            zf.ExtractAll(path);

            Monitor.Enter(gate);
            return new CompositeDisposable(ret, Disposable.Create(() => Monitor.Exit(gate)));
        }
    }
}


text:
require File.expand_path('../application', __FILE__)

# Constants
GOOGLE_ANALYTICS_CODE = "UA-3252564-8"

# Initialize the rails application
Billcrush::Application.initialize!


text:
<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="6dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways" />

        <android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="20dp"
        android:layout_gravity="end|bottom"
        android:src="@drawable/ic_add_white_18dp"
        android:visibility="gone"
        app:fabSize="normal"
        app:layout_behavior="net.testaholic.brewery.behavior.ScrollOffBottomBehavior"/>

</android.support.design.widget.CoordinatorLayout>


text:
"""Classes supporting unit and lesson editing."""

__author__ = 'John Orr (jorr@google.com)'

import cgi
import logging
import urllib
import messages

from common import utils as common_utils
from controllers import sites
from controllers.utils import ApplicationHandler
from controllers.utils import BaseRESTHandler
from controllers.utils import XsrfTokenManager
from models import courses
from models import resources_display
from models import custom_units
from models import roles
from models import transforms
from modules.oeditor import oeditor
from tools import verify

class CourseOutlineRights(object):
    """Manages view/edit rights for course outline."""

    @classmethod
    def can_view(cls, handler):
        return cls.can_edit(handler)

    @classmethod
    def can_edit(cls, handler):
        return roles.Roles.is_course_admin(handler.app_context)

    @classmethod
    def can_delete(cls, handler):
        return cls.can_edit(handler)

    @classmethod
    def can_add(cls, handler):
        return cls.can_edit(handler)

class UnitLessonEditor(ApplicationHandler):
    """An editor for the unit and lesson titles."""

    HIDE_ACTIVITY_ANNOTATIONS = [
        (['properties', 'activity_title', '_inputex'], {'_type': 'hidden'}),
        (['properties', 'activity_listed', '_inputex'], {'_type': 'hidden'}),
        (['properties', 'activity', '_inputex'], {'_type': 'hidden'}),
    ]

    def get_import_course(self):
        """Shows setup form for course import."""

        template_values = {}
        template_values['page_title'] = self.format_title('Import Course')
        annotations = ImportCourseRESTHandler.SCHEMA_ANNOTATIONS_DICT()
        if not annotations:
            template_values['main_content'] = 'No courses to import from.'
            self.render_page(template_values)
            return

        exit_url = self.canonicalize_url('/dashboard')
        rest_url = self.canonicalize_url(ImportCourseRESTHandler.URI)
        form_html = oeditor.ObjectEditor.get_html_for(
            self,
            ImportCourseRESTHandler.SCHEMA_JSON,
            annotations,
            None, rest_url, exit_url,
            auto_return=True,
            save_button_caption='Import',
            required_modules=ImportCourseRESTHandler.REQUIRED_MODULES)

        template_values = {}
        template_values['page_title'] = self.format_title('Import Course')
        template_values['page_description'] = messages.IMPORT_COURSE_DESCRIPTION
        template_values['main_content'] = form_html
        self.render_page(template_values)

    def post_add_lesson(self):
        """Adds new lesson to a first unit of the course."""
        course = courses.Course(self)
        target_unit = None
        if self.request.get('unit_id'):
            target_unit = course.find_unit_by_id(self.request.get('unit_id'))
        else:
            for unit in course.get_units():
                if unit.type == verify.UNIT_TYPE_UNIT:
                    target_unit = unit
                    break
        if target_unit:
            lesson = course.add_lesson(target_unit)
            course.save()
            # TODO(psimakov): complete 'edit_lesson' view
            self.redirect(self.get_action_url(
                'edit_lesson', key=lesson.lesson_id,
                extra_args={'is_newly_created': 1}))
        else:
            self.redirect('/dashboard')

    def post_add_unit(self):
        """Adds new unit to a course."""
        course = courses.Course(self)
        unit = course.add_unit()
        course.save()
        self.redirect(self.get_action_url(
            'edit_unit', key=unit.unit_id, extra_args={'is_newly_created': 1}))

    def post_add_link(self):
        """Adds new link to a course."""
        course = courses.Course(self)
        link = course.add_link()
        link.href = ''
        course.save()
        self.redirect(self.get_action_url(
            'edit_link', key=link.unit_id, extra_args={'is_newly_created': 1}))

    def post_add_assessment(self):
        """Adds new assessment to a course."""
        course = courses.Course(self)
        assessment = course.add_assessment()
        course.save()
        self.redirect(self.get_action_url(
            'edit_assessment', key=assessment.unit_id,
            extra_args={'is_newly_created': 1}))

    def post_add_custom_unit(self):
        """Adds a custom unit to a course."""
        course = courses.Course(self)
        custom_unit_type = self.request.get('unit_type')
        custom_unit = course.add_custom_unit(custom_unit_type)
        course.save()
        self.redirect(self.get_action_url(
            'edit_custom_unit', key=custom_unit.unit_id,
            extra_args={'is_newly_created': 1,
                        'unit_type': custom_unit_type}))

    def post_set_draft_status(self):
        """Sets the draft status of a course component.

        Only works with CourseModel13 courses, but the REST handler
        is only called with this type of courses.
        """
        key = self.request.get('key')
        if not CourseOutlineRights.can_edit(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        course = courses.Course(self)
        component_type = self.request.get('type')
        if component_type == 'unit':
            course_component = course.find_unit_by_id(key)
        elif component_type == 'lesson':
            course_component = course.find_lesson_by_id(None, key)
        else:
            transforms.send_json_response(
                self, 401, 'Invalid key.', {'key': key})
            return

        set_draft = self.request.get('set_draft')
        if set_draft == '1':
            set_draft = True
        elif set_draft == '0':
            set_draft = False
        else:
            transforms.send_json_response(
                self, 401, 'Invalid set_draft value, expected 0 or 1.',
                {'set_draft': set_draft}
            )
            return

        course_component.now_available = not set_draft
        course.save()

        transforms.send_json_response(
            self,
            200,
            'Draft status set to %s.' % (
                resources_display.DRAFT_TEXT if set_draft else
                resources_display.PUBLISHED_TEXT
            ), {
                'is_draft': set_draft
            }
        )
        return

    def _render_edit_form_for(
        self, rest_handler_cls, title, schema=None, annotations_dict=None,
        delete_xsrf_token='delete-unit', page_description=None,
        additional_dirs=None, extra_js_files=None, extra_css_files=None):
        """Renders an editor form for a given REST handler class."""
        annotations_dict = annotations_dict or []
        if schema:
            schema_json = schema.get_json_schema()
            annotations_dict = schema.get_schema_dict() + annotations_dict
        else:
            schema_json = rest_handler_cls.SCHEMA_JSON
            if not annotations_dict:
                annotations_dict = rest_handler_cls.SCHEMA_ANNOTATIONS_DICT

        key = self.request.get('key')

        extra_args = {}
        if self.request.get('is_newly_created'):
            extra_args['is_newly_created'] = 1

        exit_url = self.canonicalize_url('/dashboard')
        rest_url = self.canonicalize_url(rest_handler_cls.URI)
        delete_url = '%s?%s' % (
            self.canonicalize_url(rest_handler_cls.URI),
            urllib.urlencode({
                'key': key,
                'xsrf_token': cgi.escape(
                    self.create_xsrf_token(delete_xsrf_token))
                }))

        def extend_list(target_list, ext_name):
            # Extend the optional arg lists such as extra_js_files by an
            # optional list field on the REST handler class. Used to provide
            # seams for modules to add js files, etc. See LessonRESTHandler
            if hasattr(rest_handler_cls, ext_name):
                target_list = target_list or []
                return (target_list or []) + getattr(rest_handler_cls, ext_name)
            return target_list

        form_html = oeditor.ObjectEditor.get_html_for(
            self,
            schema_json,
            annotations_dict,
            key, rest_url, exit_url,
            extra_args=extra_args,
            delete_url=delete_url, delete_method='delete',
            read_only=not self.app_context.is_editable_fs(),
            required_modules=rest_handler_cls.REQUIRED_MODULES,
            additional_dirs=extend_list(additional_dirs, 'ADDITIONAL_DIRS'),
            extra_css_files=extend_list(extra_css_files, 'EXTRA_CSS_FILES'),
            extra_js_files=extend_list(extra_js_files, 'EXTRA_JS_FILES'))

        template_values = {}
        template_values['page_title'] = self.format_title('Edit %s' % title)
        if page_description:
            template_values['page_description'] = page_description
        template_values['main_content'] = form_html
        self.render_page(template_values)

    def get_edit_unit(self):
        """Shows unit editor."""
        self._render_edit_form_for(
            UnitRESTHandler, 'Unit',
            page_description=messages.UNIT_EDITOR_DESCRIPTION,
            annotations_dict=UnitRESTHandler.get_annotations_dict(
                courses.Course(self), int(self.request.get('key'))))

    def get_edit_custom_unit(self):
        """Shows custom_unit_editor."""
        custom_unit_type = self.request.get('unit_type')
        custom_unit = custom_units.UnitTypeRegistry.get(custom_unit_type)
        rest_handler = custom_unit.rest_handler
        self._render_edit_form_for(
            rest_handler,
            custom_unit.name,
            page_description=rest_handler.DESCRIPTION,
            annotations_dict=rest_handler.get_schema_annotations_dict(
                courses.Course(self)))

    def get_edit_link(self):
        """Shows link editor."""
        self._render_edit_form_for(
            LinkRESTHandler, 'Link',
            page_description=messages.LINK_EDITOR_DESCRIPTION)

    def get_edit_assessment(self):
        """Shows assessment editor."""
        self._render_edit_form_for(
            AssessmentRESTHandler, 'Assessment',
            page_description=messages.ASSESSMENT_EDITOR_DESCRIPTION,
            extra_js_files=['assessment_editor_lib.js', 'assessment_editor.js'])

    def get_edit_lesson(self):
        """Shows the lesson/activity editor."""
        key = self.request.get('key')
        course = courses.Course(self)
        lesson = course.find_lesson_by_id(None, key)
        annotations_dict = (
            None if lesson.has_activity
            else UnitLessonEditor.HIDE_ACTIVITY_ANNOTATIONS)
        schema = LessonRESTHandler.get_schema(course, key)
        if courses.has_only_new_style_activities(course):
            schema.get_property('objectives').extra_schema_dict_values[
              'excludedCustomTags'] = set(['gcb-activity'])
        self._render_edit_form_for(
            LessonRESTHandler, 'Lessons and Activities',
            schema=schema,
            annotations_dict=annotations_dict,
            delete_xsrf_token='delete-lesson')

class CommonUnitRESTHandler(BaseRESTHandler):
    """A common super class for all unit REST handlers."""

    # These functions are called with an updated unit object whenever a
    # change is saved.
    POST_SAVE_HOOKS = []

    def unit_to_dict(self, unit):
        """Converts a unit to a dictionary representation."""
        return resources_display.UnitTools(self.get_course()).unit_to_dict(unit)

    def apply_updates(self, unit, updated_unit_dict, errors):
        """Applies changes to a unit; modifies unit input argument."""
        resources_display.UnitTools(courses.Course(self)).apply_updates(
            unit, updated_unit_dict, errors)

    def get(self):
        """A GET REST method shared by all unit types."""
        key = self.request.get('key')

        if not CourseOutlineRights.can_view(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        unit = courses.Course(self).find_unit_by_id(key)
        if not unit:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'key': key})
            return

        message = ['Success.']
        if self.request.get('is_newly_created'):
            unit_type = verify.UNIT_TYPE_NAMES[unit.type].lower()
            message.append(
                'New %s has been created and saved.' % unit_type)

        transforms.send_json_response(
            self, 200, '\n'.join(message),
            payload_dict=self.unit_to_dict(unit),
            xsrf_token=XsrfTokenManager.create_xsrf_token('put-unit'))

    def put(self):
        """A PUT REST method shared by all unit types."""
        request = transforms.loads(self.request.get('request'))
        key = request.get('key')

        if not self.assert_xsrf_token_or_fail(
                request, 'put-unit', {'key': key}):
            return

        if not CourseOutlineRights.can_edit(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        unit = courses.Course(self).find_unit_by_id(key)
        if not unit:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'key': key})
            return

        payload = request.get('payload')
        updated_unit_dict = transforms.json_to_dict(
            transforms.loads(payload), self.SCHEMA_DICT)

        errors = []
        self.apply_updates(unit, updated_unit_dict, errors)
        if not errors:
            course = courses.Course(self)
            assert course.update_unit(unit)
            course.save()
            common_utils.run_hooks(self.POST_SAVE_HOOKS, unit)
            transforms.send_json_response(self, 200, 'Saved.')
        else:
            transforms.send_json_response(self, 412, '\n'.join(errors))

    def delete(self):
        """Handles REST DELETE verb with JSON payload."""
        key = self.request.get('key')

        if not self.assert_xsrf_token_or_fail(
                self.request, 'delete-unit', {'key': key}):
            return

        if not CourseOutlineRights.can_delete(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        course = courses.Course(self)
        unit = course.find_unit_by_id(key)
        if not unit:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'key': key})
            return

        course.delete_unit(unit)
        course.save()

        transforms.send_json_response(self, 200, 'Deleted.')

class UnitRESTHandler(CommonUnitRESTHandler):
    """Provides REST API to unit."""

    URI = '/rest/course/unit'
    SCHEMA = resources_display.ResourceUnit.get_schema(course=None, key=None)
    SCHEMA_JSON = SCHEMA.get_json_schema()
    SCHEMA_DICT = SCHEMA.get_json_schema_dict()
    REQUIRED_MODULES = [
        'inputex-string', 'inputex-select', 'inputex-uneditable',
        'inputex-list', 'inputex-hidden', 'inputex-number', 'inputex-integer',
        'inputex-checkbox', 'gcb-rte']

    @classmethod
    def get_annotations_dict(cls, course, this_unit_id):
        # The set of available assesments needs to be dynamically
        # generated and set as selection choices on the form.
        # We want to only show assessments that are not already
        # selected by other units.
        available_assessments = {}
        referenced_assessments = {}
        for unit in course.get_units():
            if unit.type == verify.UNIT_TYPE_ASSESSMENT:
                model_version = course.get_assessment_model_version(unit)
                track_labels = course.get_unit_track_labels(unit)
                # Don't allow selecting old-style assessments, which we
                # can't display within Unit page.
                # Don't allow selection of assessments with parents
                if (model_version != courses.ASSESSMENT_MODEL_VERSION_1_4 and
                    not track_labels):
                    available_assessments[unit.unit_id] = unit
            elif (unit.type == verify.UNIT_TYPE_UNIT and
                  this_unit_id != unit.unit_id):
                if unit.pre_assessment:
                    referenced_assessments[unit.pre_assessment] = True
                if unit.post_assessment:
                    referenced_assessments[unit.post_assessment] = True
        for referenced in referenced_assessments:
            if referenced in available_assessments:
                del available_assessments[referenced]

        schema = resources_display.ResourceUnit.get_schema(course, this_unit_id)
        choices = [(-1, '-- None --')]
        for assessment_id in sorted(available_assessments):
            choices.append(
                (assessment_id, available_assessments[assessment_id].title))
        schema.get_property('pre_assessment').set_select_data(choices)
        schema.get_property('post_assessment').set_select_data(choices)

        return schema.get_schema_dict()

class LinkRESTHandler(CommonUnitRESTHandler):
    """Provides REST API to link."""

    URI = '/rest/course/link'
    SCHEMA = resources_display.ResourceLink.get_schema(course=None, key=None)
    SCHEMA_JSON = SCHEMA.get_json_schema()
    SCHEMA_DICT = SCHEMA.get_json_schema_dict()
    SCHEMA_ANNOTATIONS_DICT = SCHEMA.get_schema_dict()
    REQUIRED_MODULES = [
        'inputex-string', 'inputex-select', 'inputex-uneditable',
        'inputex-list', 'inputex-hidden', 'inputex-number', 'inputex-checkbox']

class ImportCourseRESTHandler(CommonUnitRESTHandler):
    """Provides REST API to course import."""

    URI = '/rest/course/import'

    SCHEMA_JSON = """
    {
        "id": "Import Course Entity",
        "type": "object",
        "description": "Import Course",
        "properties": {
            "course" : {"type": "string"}
            }
    }
    """

    SCHEMA_DICT = transforms.loads(SCHEMA_JSON)

    REQUIRED_MODULES = [
        'inputex-string', 'inputex-select', 'inputex-uneditable']

    @classmethod
    def _get_course_list(cls):
        # Make a list of courses user has the rights to.
        course_list = []
        for acourse in sites.get_all_courses():
            if not roles.Roles.is_course_admin(acourse):
                continue
            if acourse == sites.get_course_for_current_request():
                continue

            atitle = '%s (%s)' % (acourse.get_title(), acourse.get_slug())

            course_list.append({
                'value': acourse.raw, 'label': cgi.escape(atitle)})
        return course_list

    @classmethod
    def SCHEMA_ANNOTATIONS_DICT(cls):
        """Schema annotations are dynamic and include a list of courses."""
        course_list = cls._get_course_list()
        if not course_list:
            return None

        # Format annotations.
        return [
            (['title'], 'Import Course'),
            (
                ['properties', 'course', '_inputex'],
                {
                    'label': 'Available Courses',
                    '_type': 'select',
                    'choices': course_list})]

    def get(self):
        """Handles REST GET verb and returns an object as JSON payload."""
        if not CourseOutlineRights.can_view(self):
            transforms.send_json_response(self, 401, 'Access denied.', {})
            return

        first_course_in_dropdown = self._get_course_list()[0]['value']

        transforms.send_json_response(
            self, 200, None,
            payload_dict={'course': first_course_in_dropdown},
            xsrf_token=XsrfTokenManager.create_xsrf_token(
                'import-course'))

    def put(self):
        """Handles REST PUT verb with JSON payload."""
        request = transforms.loads(self.request.get('request'))

        if not self.assert_xsrf_token_or_fail(
                request, 'import-course', {'key': None}):
            return

        if not CourseOutlineRights.can_edit(self):
            transforms.send_json_response(self, 401, 'Access denied.', {})
            return

        payload = request.get('payload')
        course_raw = transforms.json_to_dict(
            transforms.loads(payload), self.SCHEMA_DICT)['course']

        source = None
        for acourse in sites.get_all_courses():
            if acourse.raw == course_raw:
                source = acourse
                break

        if not source:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'raw': course_raw})
            return

        course = courses.Course(self)
        errors = []
        try:
            course.import_from(source, errors)
        except Exception as e:  # pylint: disable=broad-except
            logging.exception(e)
            errors.append('Import failed: %s' % e)

        if errors:
            transforms.send_json_response(self, 412, '\n'.join(errors))
            return

        course.save()
        transforms.send_json_response(self, 200, 'Imported.')

class AssessmentRESTHandler(CommonUnitRESTHandler):
    """Provides REST API to assessment."""

    URI = '/rest/course/assessment'

    SCHEMA = resources_display.ResourceAssessment.get_schema(
        course=None, key=None)

    SCHEMA_JSON = SCHEMA.get_json_schema()

    SCHEMA_DICT = SCHEMA.get_json_schema_dict()

    SCHEMA_ANNOTATIONS_DICT = SCHEMA.get_schema_dict()

    REQUIRED_MODULES = [
        'gcb-rte', 'inputex-select', 'inputex-string', 'inputex-textarea',
        'inputex-uneditable', 'inputex-integer', 'inputex-hidden',
        'inputex-checkbox', 'inputex-list']

class UnitLessonTitleRESTHandler(BaseRESTHandler):
    """Provides REST API to reorder unit and lesson titles."""

    URI = '/rest/course/outline'
    XSRF_TOKEN = 'unit-lesson-reorder'

    SCHEMA_JSON = """
        {
            "type": "object",
            "description": "Course Outline",
            "properties": {
                "outline": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "id": {"type": "string"},
                            "title": {"type": "string"},
                            "lessons": {
                                "type": "array",
                                "items": {
                                    "type": "object",
                                    "properties": {
                                        "id": {"type": "string"},
                                        "title": {"type": "string"}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        """

    SCHEMA_DICT = transforms.loads(SCHEMA_JSON)

    def put(self):
        """Handles REST PUT verb with JSON payload."""
        request = transforms.loads(self.request.get('request'))

        if not self.assert_xsrf_token_or_fail(
                request, self.XSRF_TOKEN, {'key': None}):
            return

        if not CourseOutlineRights.can_edit(self):
            transforms.send_json_response(self, 401, 'Access denied.', {})
            return

        payload = request.get('payload')
        payload_dict = transforms.json_to_dict(
            transforms.loads(payload), self.SCHEMA_DICT)
        course = courses.Course(self)
        course.reorder_units(payload_dict['outline'])
        course.save()

        transforms.send_json_response(self, 200, 'Saved.')

class LessonRESTHandler(BaseRESTHandler):
    """Provides REST API to handle lessons and activities."""

    URI = '/rest/course/lesson'

    REQUIRED_MODULES = [
        'inputex-string', 'gcb-rte', 'inputex-select', 'inputex-textarea',
        'inputex-uneditable', 'inputex-checkbox', 'inputex-hidden']

    # Enable modules to specify locations to load JS and CSS files
    ADDITIONAL_DIRS = []
    # Enable modules to add css files to be shown in the editor page.
    EXTRA_CSS_FILES = []
    # Enable modules to add js files to be shown in the editor page.
    EXTRA_JS_FILES = []

    # Enable other modules to add transformations to the schema.Each member must
    # be a function of the form:
    #     callback(lesson_field_registry)
    # where the argument is the root FieldRegistry for the schema
    SCHEMA_LOAD_HOOKS = []

    # Enable other modules to add transformations to the load. Each member must
    # be a function of the form:
    #     callback(lesson, lesson_dict)
    # and the callback should update fields of the lesson_dict, which will be
    # returned to the caller of a GET request.
    PRE_LOAD_HOOKS = []

    # Enable other modules to add transformations to the save. Each member must
    # be a function of the form:
    #     callback(lesson, lesson_dict)
    # and the callback should update fields of the lesson with values read from
    # the dict which was the payload of a PUT request.
    PRE_SAVE_HOOKS = []

    # These functions are called with an updated lesson object whenever a
    # change is saved.
    POST_SAVE_HOOKS = []

    @classmethod
    def get_schema(cls, course, key):
        lesson_schema = resources_display.ResourceLesson.get_schema(course, key)
        common_utils.run_hooks(cls.SCHEMA_LOAD_HOOKS, lesson_schema)
        return lesson_schema

    @classmethod
    def get_lesson_dict(cls, course, lesson):
        return cls.get_lesson_dict_for(course, lesson)

    @classmethod
    def get_lesson_dict_for(cls, course, lesson):
        lesson_dict = resources_display.ResourceLesson.get_data_dict(
            course, lesson.lesson_id)
        common_utils.run_hooks(cls.PRE_LOAD_HOOKS, lesson, lesson_dict)
        return lesson_dict

    def get(self):
        """Handles GET REST verb and returns lesson object as JSON payload."""

        if not CourseOutlineRights.can_view(self):
            transforms.send_json_response(self, 401, 'Access denied.', {})
            return

        key = self.request.get('key')
        course = courses.Course(self)
        lesson = course.find_lesson_by_id(None, key)
        assert lesson
        payload_dict = self.get_lesson_dict(course, lesson)

        message = ['Success.']
        if self.request.get('is_newly_created'):
            message.append('New lesson has been created and saved.')

        transforms.send_json_response(
            self, 200, '\n'.join(message),
            payload_dict=payload_dict,
            xsrf_token=XsrfTokenManager.create_xsrf_token('lesson-edit'))

    def put(self):
        """Handles PUT REST verb to save lesson and associated activity."""
        request = transforms.loads(self.request.get('request'))
        key = request.get('key')

        if not self.assert_xsrf_token_or_fail(
                request, 'lesson-edit', {'key': key}):
            return

        if not CourseOutlineRights.can_edit(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        course = courses.Course(self)
        lesson = course.find_lesson_by_id(None, key)
        if not lesson:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'key': key})
            return

        payload = request.get('payload')
        updates_dict = transforms.json_to_dict(
            transforms.loads(payload),
            self.get_schema(course, key).get_json_schema_dict())

        lesson.title = updates_dict['title']
        lesson.unit_id = updates_dict['unit_id']
        lesson.scored = (updates_dict['scored'] == 'scored')
        lesson.objectives = updates_dict['objectives']
        lesson.video = updates_dict['video']
        lesson.notes = updates_dict['notes']
        lesson.auto_index = updates_dict['auto_index']
        lesson.activity_title = updates_dict['activity_title']
        lesson.activity_listed = updates_dict['activity_listed']
        lesson.manual_progress = updates_dict['manual_progress']
        lesson.now_available = not updates_dict['is_draft']

        activity = updates_dict.get('activity', '').strip()
        errors = []
        if activity:
            if lesson.has_activity:
                course.set_activity_content(lesson, activity, errors=errors)
            else:
                errors.append('Old-style activities are not supported.')
        else:
            lesson.has_activity = False
            fs = self.app_context.fs
            path = fs.impl.physical_to_logical(course.get_activity_filename(
                lesson.unit_id, lesson.lesson_id))
            if fs.isfile(path):
                fs.delete(path)

        if not errors:
            common_utils.run_hooks(self.PRE_SAVE_HOOKS, lesson, updates_dict)
            assert course.update_lesson(lesson)
            course.save()
            common_utils.run_hooks(self.POST_SAVE_HOOKS, lesson)
            transforms.send_json_response(self, 200, 'Saved.')
        else:
            transforms.send_json_response(self, 412, '\n'.join(errors))

    def delete(self):
        """Handles REST DELETE verb with JSON payload."""
        key = self.request.get('key')

        if not self.assert_xsrf_token_or_fail(
                self.request, 'delete-lesson', {'key': key}):
            return

        if not CourseOutlineRights.can_delete(self):
            transforms.send_json_response(
                self, 401, 'Access denied.', {'key': key})
            return

        course = courses.Course(self)
        lesson = course.find_lesson_by_id(None, key)
        if not lesson:
            transforms.send_json_response(
                self, 404, 'Object not found.', {'key': key})
            return

        assert course.delete_lesson(lesson)
        course.save()

        transforms.send_json_response(self, 200, 'Deleted.')