text:
from common_fixtures import *  # NOQA
from gdapi import ApiError

def _user_preference(client, name=None):
    if name is None:
        name = random_str()
    preference = client.wait_success(client.create_user_preference(
        name=name, value=random_str()))
    got_preference = client.by_id('userPreference', preference.id)
    assert preference.id == got_preference.id
    assert name == got_preference.name
    assert preference.value == got_preference.value
    return got_preference

def test_create_user_preference(user_client):
    _user_preference(user_client)

def test_delete_user_preference(user_client):
    preference = _user_preference(user_client)
    preference = user_client.wait_success(preference.deactivate())
    preference = user_client.wait_success(preference.remove())
    preference = user_client.wait_success(preference.purge())
    preference = user_client.by_id('userPreference', preference.id)
    assert preference.state == 'purged'

def test_update_user_preference(user_client):
    preference = _user_preference(user_client)
    new_value = random_str()
    user_client.update(preference, value=new_value)
    got_preference = user_client.by_id('userPreference', preference.id)
    assert got_preference.value == new_value

def test_unique_user_preference(user_client, admin_user_client):
    rand_str = random_str()
    _user_preference(user_client, rand_str)
    with pytest.raises(ApiError) as e:
        _user_preference(user_client, rand_str)
    assert e.value.error.status == 422
    _user_preference(admin_user_client, rand_str)
    with pytest.raises(ApiError) as e:
        _user_preference(admin_user_client, rand_str)
    assert e.value.error.status == 422


text:
package org.scaladebugger.api.profiles.swappable.info
import org.scalamock.scalatest.MockFactory
import org.scalatest.{FunSpec, Matchers, ParallelTestExecution}
import org.scaladebugger.api.profiles.ProfileManager
import org.scaladebugger.api.profiles.swappable.SwappableDebugProfile
import org.scaladebugger.api.profiles.traits.DebugProfile
import org.scaladebugger.api.profiles.traits.info.ValueInfo
import org.scaladebugger.test.helpers.ParallelMockFunSpec

class SwappableMiscInfoSpec extends ParallelMockFunSpec
{
  private val mockDebugProfile = mock[DebugProfile]
  private val mockProfileManager = mock[ProfileManager]

  private val swappableDebugProfile = new Object with SwappableDebugProfile {
    override protected val profileManager: ProfileManager = mockProfileManager
  }

  describe("SwappableMiscInfo") {
    describe("#availableLinesForFile") {
      it("should invoke the method on the underlying profile") {
        val expected = Some(Seq(1, 2, 3))
        val fileName = "some file"

        (mockProfileManager.retrieve _).expects(*)
          .returning(Some(mockDebugProfile)).once()

        (mockDebugProfile.availableLinesForFile _).expects(fileName)
          .returning(expected).once()

        val actual = swappableDebugProfile.availableLinesForFile(fileName)

        actual should be (expected)
      }

      it("should throw an exception if there is no underlying profile") {
        val fileName = "some file"

        (mockProfileManager.retrieve _).expects(*).returning(None).once()

        intercept[AssertionError] {
          swappableDebugProfile.availableLinesForFile(fileName)
        }
      }
    }

    describe("#createRemotely(AnyVal)") {
      it("should invoke the method on the underlying profile") {
        val expected = mock[ValueInfo]
        val value: AnyVal = 33

        (mockProfileManager.retrieve _).expects(*)
          .returning(Some(mockDebugProfile)).once()

        (mockDebugProfile.createRemotely(_: AnyVal)).expects(value)
          .returning(expected).once()

        val actual = swappableDebugProfile.createRemotely(value)

        actual should be (expected)
      }

      it("should throw an exception if there is no underlying profile") {
        val value = "some string"

        (mockProfileManager.retrieve _).expects(*).returning(None).once()

        intercept[AssertionError] {
          swappableDebugProfile.createRemotely(value)
        }
      }
    }

    describe("#createRemotely(String)") {
      it("should invoke the method on the underlying profile") {
        val expected = mock[ValueInfo]
        val value = "some string"

        (mockProfileManager.retrieve _).expects(*)
          .returning(Some(mockDebugProfile)).once()

        (mockDebugProfile.createRemotely(_: String)).expects(value)
          .returning(expected).once()

        val actual = swappableDebugProfile.createRemotely(value)

        actual should be (expected)
      }

      it("should throw an exception if there is no underlying profile") {
        val value = "some string"

        (mockProfileManager.retrieve _).expects(*).returning(None).once()

        intercept[AssertionError] {
          swappableDebugProfile.createRemotely(value)
        }
      }
    }

    describe("#sourceNameToPaths") {
      it("should invoke the method on the underlying profile") {
        val expected = Seq("path/to/file.scala")
        val sourceName = "file.scala"

        (mockProfileManager.retrieve _).expects(*)
          .returning(Some(mockDebugProfile)).once()

        (mockDebugProfile.sourceNameToPaths _).expects(sourceName)
          .returning(expected).once()

        val actual = swappableDebugProfile.sourceNameToPaths(sourceName)

        actual should be (expected)
      }

      it("should throw an exception if there is no underlying profile") {
        val sourceName = "file.scala"

        (mockProfileManager.retrieve _).expects(*).returning(None).once()

        intercept[AssertionError] {
          swappableDebugProfile.availableLinesForFile(sourceName)
        }
      }
    }

    describe("#mainClassName") {
      it("should invoke the method on the underlying profile") {
        val expected = "some class name"

        (mockProfileManager.retrieve _).expects(*)
          .returning(Some(mockDebugProfile)).once()

        (mockDebugProfile.mainClassName _).expects().returning(expected).once()

        val actual = swappableDebugProfile.mainClassName

        actual should be (expected)
      }

      it("should throw an exception if there is no underlying profile") {
        (mockProfileManager.retrieve _).expects(*).returning(None).once()

        intercept[AssertionError] {
          swappableDebugProfile.mainClassName
        }
      }
    }

    describe("#commandLineArguments") {
      it("should invoke the method on the underlying profile") {
        val expected = Seq("some", "arguments")

        (mockProfileManager.retrieve _).expects(*)
          .returning(Some(mockDebugProfile)).once()

        (mockDebugProfile.commandLineArguments _).expects()
          .returning(expected).once()

        val actual = swappableDebugProfile.commandLineArguments

        actual should be (expected)
      }

      it("should throw an exception if there is no underlying profile") {
        (mockProfileManager.retrieve _).expects(*).returning(None).once()

        intercept[AssertionError] {
          swappableDebugProfile.mainClassName
        }
      }
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
@interface CBLArrayDiff (UIKit)

- (void) animateTableView: (UITableView*)tableView
        deletionAnimation: (UITableViewRowAnimation)deletionAnimation
         replaceAnimation: (UITableViewRowAnimation)replaceAnimation
       insertionAnimation: (UITableViewRowAnimation)insertionAnimation;

@end


text:
(function() {
  // properties

  const path = require("path");
  const xmlHelper = require("../lib/xmlHelper.js");

  // entry
  module.exports = {
    read: read
  };

  // read branch config from config.xml
  function read(context) {
    const projectRoot = getProjectRoot(context);
    const configXml = getConfigXml(projectRoot);
    const branchXml = getBranchXml(configXml);
    const branchPreferences = getBranchPreferences(
      context,
      configXml,
      branchXml
    );

    validateBranchPreferences(branchPreferences);

    return branchPreferences;
  }

  // read config.xml
  function getConfigXml(projectRoot) {
    const pathToConfigXml = path.join(projectRoot, "config.xml");
    const configXml = xmlHelper.readXmlAsJson(pathToConfigXml);

    if (configXml == null) {
      throw new Error(
        "BRANCH SDK: A config.xml is not found in project's root directory. Docs https://goo.gl/GijGKP"
      );
    }

    return configXml;
  }

  // read <branch-config> within config.xml
  function getBranchXml(configXml) {
    const branchConfig = configXml.widget["branch-config"];

    if (branchConfig == null || branchConfig.length === 0) {
      throw new Error(
        "BRANCH SDK: <branch-config> tag is not set in the config.xml. Docs https://goo.gl/GijGKP"
      );
    }

    return branchConfig[0];
  }

  // read <branch-config> properties within config.xml
  function getBranchPreferences(context, configXml, branchXml) {
    return {
      projectRoot: getProjectRoot(context),
      projectName: getProjectName(configXml),
      branchKey: getBranchKey(branchXml, "branch-key-live"),
      branchKeyTest: getBranchValue(branchXml, "branch-key-test"),
      branchTestMode: getBranchValue(branchXml, "branch-test-mode"),
      linkDomain: getBranchLinkDomains(branchXml, "link-domain"),
      androidLinkDomain: getBranchLinkDomains(branchXml, "android-link-domain"),
      iosLinkDomain: getBranchLinkDomains(branchXml, "ios-link-domain"),
      uriScheme: getBranchValue(branchXml, "uri-scheme"),
      iosBundleId: getBundleId(configXml, "ios"),
      iosProjectModule: getProjectModule(context),
      iosTeamRelease: getBranchValue(branchXml, "ios-team-release"), // optional
      iosTeamDebug: getBranchValue(branchXml, "ios-team-debug"), // optional
      androidBundleId: getBundleId(configXml, "android"), // optional
      androidPrefix: getBranchValue(branchXml, "android-prefix"), // optional
      androidTestMode: getBranchValue(branchXml, "android-testmode") // DEPRECATED optional
    };
  }

  // read project root from cordova context
  function getProjectRoot(context) {
    return context.opts.projectRoot || null;
  }

  // read project name from config.xml
  function getProjectName(configXml) {
    let output = null;
    if (configXml.widget.hasOwnProperty("name")) {
      const name = configXml.widget.name[0];
      if (typeof name === "string") {
        // handle <name>Branch Cordova</name>
        output = configXml.widget.name[0];
      } else {
        // handle <name short="Branch">Branch Cordova</name>
        output = configXml.widget.name[0]._;
      }
    }

    return output;
  }

  // read branch value from <branch-config>
  function getBranchValue(branchXml, key) {
    return branchXml.hasOwnProperty(key) ? branchXml[key][0].$.value : null;
  }

  // read branch value from (<branch-key> DEPRECATED)
  // or <branch-key-live>
  function getBranchKey(branchXml) {
    return getBranchValue(branchXml, "branch-key-live") || getBranchValue(branchXml, "branch-key");
  }

  // read branch value from <branch-config>
  // for multiple <link-domain>, <android-link-domain> or <ios-link-domain>
  function getBranchLinkDomains(branchXml, key) {
    const output = [];
    if (branchXml.hasOwnProperty(key)) {
      for (let i = 0; i < branchXml[key].length; i++) {
        const item = branchXml[key][i];
        output.push(item.$.value);
      }
    }
    return output;
  }

  // read bundle id from config.xml (optional values override widget-id)
  function getBundleId(configXml, platform) {
    let output = null;
    const key =
      platform === "ios" ? "ios-CFBundleIdentifier" : "android-packageName";

    if (configXml.widget.$.hasOwnProperty(key)) {
      output = configXml.widget.$[key];
    } else if (configXml.widget.$.hasOwnProperty("id")) {
      output = configXml.widget.$.id;
    }

    return output;
  }

  // read iOS project module from cordova context
  function getProjectModule(context) {
    const projectRoot = getProjectRoot(context);
    const projectPath = path.join(projectRoot, "platforms", "ios");

    try {
      // pre 5.0 cordova structure
      return context
        .requireCordovaModule("cordova-lib/src/plugman/platforms")
        .ios.parseProjectFile(projectPath);
    } catch (e) {
      try {
        // pre 7.0 cordova structure
        return context
          .requireCordovaModule("cordova-lib/src/plugman/platforms/ios")
          .parseProjectFile(projectPath);
      } catch (e) {
        // post 7.0 cordova structure
        return getProjectModuleGlob(context);
      }
    }
  }

  function getProjectModuleGlob(context) {
    // get xcodeproj
    const projectRoot = getProjectRoot(context);
    const projectPath = path.join(projectRoot, "platforms", "ios");
    const projectFiles = require("glob")
      .sync(path.join(projectPath, "*.xcodeproj", "project.pbxproj"));
    if (projectFiles.length === 0) return;
    const pbxPath = projectFiles[0];
    const xcodeproj = require("xcode").project(pbxPath);

    // add hash
    xcodeproj.parseSync();

    // return xcodeproj and write method
    return {
      xcode: xcodeproj,
      write: function() {
        // save xcodeproj
        const fs = require("fs");
        fs.writeFileSync(pbxPath, xcodeproj.writeSync());

        // pull framework dependencies
        const frameworksFile = path.join(projectPath, "frameworks.json");
        let frameworks = {};

        try {
          frameworks = require(frameworksFile);
        } catch (e) {}
        // If there are no framework references, remove this file
        if (Object.keys(frameworks).length === 0) {
          return require("shelljs")
            .rm("-rf", frameworksFile);
        }

        // save frameworks
        fs.writeFileSync(frameworksFile, JSON.stringify(frameworks, null, 4));
      }
    };
  }

  // validate <branch-config> properties within config.xml
  function validateBranchPreferences(preferences) {
    if (preferences.projectRoot === null) {
      throw new Error(
        'BRANCH SDK: Invalid "root" in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (preferences.projectPlatform === null) {
      throw new Error(
        'BRANCH SDK: Invalid "platform" in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (preferences.projectName === null) {
      throw new Error(
        'BRANCH SDK: Invalid "name" in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (preferences.branchKey === null && preferences.branchKeyLive === null) {
      throw new Error(
        'BRANCH SDK: Invalid "branch-key-live" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (preferences.branchKey === null && preferences.branchKeyTest === null) {
      throw new Error(
        'BRANCH SDK: Invalid "branch-key-test" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      preferences.uriScheme === null ||
      !/^[a-zA-Z0-9-.]+$/.test(preferences.uriScheme)
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "uri-scheme" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      !/^(?!.*?www).*([a-zA-Z0-9]+(\.[a-zA-Z0-9]+)+.*)$/.test(
        [...preferences.linkDomain, ...preferences.androidLinkDomain, preferences.iosLinkDomain]
      )
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "link-domain" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      preferences.iosBundleId === null ||
      !/^[a-zA-Z0-9.-]+$/.test(preferences.iosBundleId)
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "id" or "ios-CFBundleIdentifier" in <widget> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      preferences.iosTeamRelease !== null &&
      !/^[a-zA-Z0-9]{10}$/.test(preferences.iosTeamRelease)
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "ios-team-release" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      preferences.iosTeamDebug !== null &&
      !/^[a-zA-Z0-9]{10}$/.test(preferences.iosTeamDebug)
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "ios-team-debug" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      preferences.androidBundleId !== null &&
      !/^[a-zA-Z0-9._]+$/.test(preferences.androidBundleId)
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "id" or "android-packageName" in <widget> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      preferences.androidPrefix !== null &&
      !/^[/].[a-zA-Z0-9]{3,4}$/.test(preferences.androidPrefix)
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "android-prefix" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      !(
        preferences.androidTestMode === "true" ||
        preferences.androidTestMode === "false" ||
        preferences.androidTestMode === null
      )
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "android-testmode" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
    if (
      !(
        preferences.branchTestMode === "true" ||
        preferences.branchTestMode === "false" ||
        preferences.branchTestMode === null
      )
    ) {
      throw new Error(
        'BRANCH SDK: Invalid "branch-test-mode" in <branch-config> in your config.xml. Docs https://goo.gl/GijGKP'
      );
    }
  }
})();


text:
<!DOCTYPE html>
<title>::slotted rules should be associated with the correct cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">

Test passes if there is a filled green square and no red.

</target>


text:
package workbench.db.postgres;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Types;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import workbench.log.LogMgr;
import workbench.resource.Settings;

import workbench.db.ColumnIdentifier;
import workbench.db.DbMetadata;
import workbench.db.DbObject;
import workbench.db.EnumIdentifier;
import workbench.db.ObjectListExtender;
import workbench.db.WbConnection;

import workbench.storage.DataStore;

import workbench.util.CollectionUtil;
import workbench.util.SqlUtil;
import workbench.util.StringUtil;

/**
 * A class to read the defined ENUM types from Postgres.
 *
 * @author Thomas Kellerer
 */
public class PostgresEnumReader
	implements ObjectListExtender
{
	final	String baseSql = "select current_database() as enum_catalog, \n" +
             "       n.nspname as enum_schema,  \n" +
             "       t.typname as enum_name,  \n" +
             "       e.enumlabel as enum_value,  \n" +
             "       obj_description(t.oid) as remarks \n" +
             "from pg_type t \n" +
             "   join pg_enum e on t.oid = e.enumtypid  \n" +
             "   join pg_catalog.pg_namespace n ON n.oid = t.typnamespace";

	@Override
	public EnumIdentifier getObjectDefinition(WbConnection con, DbObject obj)
	{
		if (obj == null) return null;

		Statement stmt = null;
		ResultSet rs = null;
		Savepoint sp = null;

		String enumName = obj.getObjectName();
		String sql = "SELECT * FROM (" + baseSql + ") ei ";
		sql += " WHERE enum_name = '" + con.getMetadata().quoteObjectname(enumName) + "' ";

		String schema = obj.getSchema();
		if (StringUtil.isNonBlank(schema))
		{
			sql += " AND enum_schema = '"  + con.getMetadata().quoteObjectname(schema) + "'";
		}

		EnumIdentifier enumDef = null;

		try
		{
			sp = con.setSavepoint();
			stmt = con.createStatementForQuery();
			rs = stmt.executeQuery(sql);

			if (rs.next())
			{
				String cat = rs.getString("enum_catalog");
				String eschema = rs.getString("enum_schema");
				String name = rs.getString("enum_name");
				String value = rs.getString("enum_value");
				String comment = rs.getString("remarks");
				enumDef = new EnumIdentifier(cat, eschema, name);
				enumDef.setComment(comment);
				enumDef.addEnumValue(value);
			}

			while (rs.next())
			{
				String value = rs.getString("enum_value");
				enumDef.addEnumValue(value);
			}

			con.releaseSavepoint(sp);
		}
		catch (SQLException e)
		{
			con.rollback(sp);
			LogMgr.logError("PostgresEnumReader.getEnumValues()", "Could not read enum values", e);
		}
		finally
		{
			SqlUtil.closeAll(rs, stmt);
		}
		return enumDef;
	}

	private String getSql(WbConnection con, String schema, String namePattern)
	{
		StringBuilder sql = new StringBuilder(baseSql.length() + 50);
		sql.append("SELECT * FROM (");
		sql.append(baseSql);
		sql.append(") ei ");

		boolean whereAdded = false;

		if (StringUtil.isNonBlank(namePattern))
		{
			sql.append("\n WHERE enum_name like '");
			sql.append(SqlUtil.escapeUnderscore(namePattern, con));
			sql.append("%' ");
			SqlUtil.appendEscapeClause(sql, con, namePattern);
			whereAdded = true;
		}

		if (StringUtil.isNonBlank(schema))
		{
			sql.append(whereAdded ? " AND " : " WHERE ");
			sql.append(" enum_schema = '");
			sql.append(schema);
			sql.append("'");
		}

		sql.append("\n ORDER BY 2");
		if (Settings.getInstance().getDebugMetadataSql())
		{
			LogMgr.logDebug("PostgresEnumReader.getSql()", "Using SQL=\n" + sql);
		}
		return sql.toString();
	}

	public Collection<EnumIdentifier> getDefinedEnums(WbConnection con, String schema, String namePattern)
	{
		Map<String, EnumIdentifier> enums = getEnumInfo(con, schema, namePattern);
		return enums.values();
	}

	public Map<String, EnumIdentifier> getEnumInfo(WbConnection con, String schemaName, String namePattern)
	{
		String sql = getSql(con, schemaName, namePattern);

		Statement stmt = null;
		ResultSet rs = null;
		Savepoint sp = null;
		Map<String, EnumIdentifier> enums = new HashMap<>();

		try
		{
			sp = con.setSavepoint();
			stmt = con.createStatementForQuery();
			rs = stmt.executeQuery(sql);
			while (rs.next())
			{
				String cat = rs.getString("enum_catalog");
				String schema = rs.getString("enum_schema");
				String name = rs.getString("enum_name");
				String value = rs.getString("enum_value");
				String comment = rs.getString("remarks");
				EnumIdentifier enumDef = enums.get(name);
				if (enumDef == null)
				{
					enumDef = new EnumIdentifier(cat, schema, name);
					enumDef.setComment(comment);
					enums.put(name, enumDef);
				}
				enumDef.addEnumValue(value);
			}
			con.releaseSavepoint(sp);
		}
		catch (SQLException e)
		{
			con.rollback(sp);
			LogMgr.logError("PostgresEnumReader.getEnumValues()", "Could not read enum values", e);
		}
		finally
		{
			SqlUtil.closeAll(rs, stmt);
		}
		return enums;
	}

	@Override
	public boolean extendObjectList(WbConnection con, DataStore result, String catalog, String schema, String objects, String[] requestedTypes)
	{
		if (!handlesType(requestedTypes)) return false;
		if (!DbMetadata.typeIncluded("ENUM", requestedTypes)) return false;

		Collection<EnumIdentifier> enums = getDefinedEnums(con, schema, objects);
		if (CollectionUtil.isEmpty(enums)) return false;

		for (EnumIdentifier enumDef : enums)
		{
			int row = result.addRow();
			result.setValue(row, DbMetadata.COLUMN_IDX_TABLE_LIST_CATALOG, null);
			result.setValue(row, DbMetadata.COLUMN_IDX_TABLE_LIST_SCHEMA, enumDef.getSchema());
			result.setValue(row, DbMetadata.COLUMN_IDX_TABLE_LIST_NAME, enumDef.getObjectName());
			result.setValue(row, DbMetadata.COLUMN_IDX_TABLE_LIST_REMARKS, enumDef.getComment());
			result.setValue(row, DbMetadata.COLUMN_IDX_TABLE_LIST_TYPE, enumDef.getObjectType());
			result.getRow(row).setUserObject(enumDef);
		}
		return true;
	}

	@Override
	public List<String> supportedTypes()
	{
		return Collections.singletonList("ENUM");
	}

	@Override
	public boolean handlesType(String type)
	{
		return StringUtil.equalStringIgnoreCase("ENUM", type);
	}

	@Override
	public boolean handlesType(String[] types)
	{
		if (types == null) return true;
		for (String type : types)
		{
			if (handlesType(type)) return true;
		}
		return false;
	}

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

	@Override
	public DataStore getObjectDetails(WbConnection con, DbObject object)
	{
		EnumIdentifier id = getObjectDefinition(con, object);
		if (id == null) return null;

		String[] columns = new String[] { "ENUM", "VALUES", "REMARKS" };
		int[] types = new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };
		int[] sizes = new int[] { 20, 30, 30 };
		DataStore result = new DataStore(columns, types, sizes);
		result.addRow();
		result.setValue(0, 0, id.getObjectName());
		result.setValue(0, 1, StringUtil.listToString(id.getValues(), ','));
		result.setValue(0, 2, id.getComment());
		return result;
	}

	@Override
	public String getObjectSource(WbConnection con, DbObject object)
	{
		if (object == null) return null;
		EnumIdentifier id = getObjectDefinition(con, object);
		if (id == null) return null;

		StringBuilder result = new StringBuilder(50);
		result.append("CREATE TYPE ");
		result.append(id.getObjectName());
		result.append(" AS ENUM (");
		String values = StringUtil.listToString(id.getValues(), ",", true, '\'');
		result.append(values);
		result.append(");\n");
		if (StringUtil.isNonBlank(id.getComment()))
		{
			result.append("\nCOMMENT ON TYPE ");
			result.append(id.getObjectName());
			result.append(" IS '");
			result.append(SqlUtil.escapeQuotes(id.getComment()));
			result.append("';\n");
		}
		return result.toString();
	}

  @Override
  public List<ColumnIdentifier> getColumns(WbConnection con, DbObject object)
  {
    return null;
  }

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


text:
from twilio.rest import Client

# Your Account Sid and Auth Token from twilio.com/user/account
account_sid = "AC850685e1d9b8c09dae0b938923dc0d42"
auth_token = "your_auth_token"
client = Client(account_sid, auth_token)

fax = client.fax.v1.faxes.create(
    from_="Jack",
    to="sip:kate@example.com",
    media_url="https://www.twilio.com/docs/documents/25/justthefaxmaam.pdf"
)

print(fax.sid)


text:
export SETTINGS='test'
export POSTGRES_USER='postgres'
export POSTGRES_PASSWORD='password'
export POSTGRES_HOST='172.16.42.43'
export POSTGRES_PORT=5432
export POSTGRES_DB='test_register_data'
export ELASTICSEARCH_ENDPOINT_URI='http://localhost:9200'
export MAX_NUMBER_SEARCH_RESULTS=7
export SEARCH_RESULTS_PER_PAGE=3
export ELASTICSEARCH_INDEX_NAME='test-landregistry'


text:
title: Extending your SharePoint 2007 site with Microsoft ASP.NET AJAX 1.0
page_title: Extending your SharePoint 2007 site with Microsoft ASP.NET AJAX 1.0 | UI for ASP.NET AJAX Documentation
description: Extending your SharePoint 2007 site with Microsoft ASP.NET AJAX 1.0
slug: sharepoint/2007/extending-your-sharepoint-2007-site-with-microsoft-asp.net-ajax-1.0
tags: extending,your,sharepoint,2007,site,with,microsoft,asp.net,ajax,1.0
published: True
position: 1
---

# Extending your SharePoint 2007 site with Microsoft ASP.NET AJAX 1.0

In order to extend your SharePoint 2007 site with Microsoft ASP.NET AJAX 1.0, you need to perform the following steps:

## Install ASP.NET Ajax 1.0

Download and install ASP.NET Ajax from [here](http://www.microsoft.com/downloads/details.aspx?FamilyID=ca9d90fa-e8c9-42e3-aa19-08e2c027f5d6&displaylang=en). You need to install "ASP.NET AJAX Extensions 1.0", which is the version built for ASP.NET 2.0

## Modify your web.config file

After ASP.NET Ajax has been installed you need to modify the web.config file of your MOSS web site with a few Ajax specific entries. Typically, the web.config file is located in `c:\inetpub\wwwroot\wss\virtualdirectories\80`

1. Add the following **`<sectionGroup>`** element in the **`<configSections>`** tag:

	**XML**

	    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
	        <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

	            <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">

	            </sectionGroup>
	        </sectionGroup>
	    </sectionGroup>

1. Add the following **`<controls>`** section as a child of the **`<system.web>/<pages>`** tag:

	**XML**

	    <controls>
	       <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
	    </controls>

1. Add the following tag to the **`<assemblies>`** tag, within the **`<compilation>`** element:

	**XML**

	    <add assembly="System.Web.Extensions, Version=1.0.61025.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

1. Register the following HTTP handlers at the end of the **`<httpHandlers>`** section:

	**XML**

	    <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
	    <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
	    <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>

1. Add the following HTTP module registration to the **`<httpModules>*`* section beneath any existing modules:

	**XML**

	    <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

1. Add a SafeControl entry for the System.Web.UI namespace from the System.Web.Extensions assembly within the **`<SharePoint>/<SafeControls>`** section:

	**XML**

	    <SafeControl Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
	        Namespace="System.Web.UI" TypeName="*" Safe="True" />

1. Finally, add the following configuration tags at the bottom of web.config, just before the end of the **`<configuration>`** tag:

	**XML**

	    <system.web.extensions>

	       </system.web.extensions>
	       <system.webServer>
	       <validation validateIntegratedModeConfiguration="false"/>
	       <modules>
	         <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>d
	       </modules>
	       <handlers>
	         <remove name="WebServiceHandlerFactory-Integrated" />
	         <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
	              type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
	         <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
	         <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
	       </handlers>
	    </system.webServer>

## See Also

 * [Extending your SharePoint 2007 site with Microsoft ASP.NET AJAX 3.5]({%slug sharepoint/2007/extending-your-sharepoint-2007-site-with-microsoft-asp.net-ajax-3.5%})


text:
# What you can borrow from Yandex frontend dev

This article is a text version of a [presentation](https://vimeo.com/53219242)
given at [Riga WebConf](http://webconf.lv/) in November 2012.

The article sums up [Yandex](http://www.yandex.com/) over 7-year experience
in finding solutions for efficient frontend development.

Yandex, as a search engine and the larges Internet company in Russia, enjoys
the maijor share of the local market and provides over a hundred of associated
services with the help of 2500 developers and 150 frontend engineers among them.

Yandex developers jointly produce solutions for the problems they run into. At
the same time, Yandexoids are truly nerds connected to the world outside Yandex
via conferences, hackatons and meetups. So, the solutions produced by Yandex
developers perfectly work outside and can be easily shared.

Here is a piece of such sharing.

## Web Interface

Look at the draft for an online shop. As you can see, it's nothing special.
Just an ordinary web site providing all the generally accepted possibilities,
such as navigation through the site pages, searching books, some advertising
parts and so on.

As web developers, you know that behind the page there are our dear HTML and CSS.

````js
    <!DOCTYPE html>
    <html>
        <head>...</head>
        <body>
            ...
        </body>

    body {
        font: 0.8em Arial, sans-serif;
        margin: 0;
        color: black;
    }
    .sidebar ul li {
````

Also, besides the page is really combination of HTML and CSS, it's also a set of
interface pieces.

Each piece is to do something. It provides to a user a functional or design
point.

Each has its purpose, similar to pieces of furniture…

A chair is to sit on, a cupboard it to keep the kitchen things. A bed is to lay
on, and a coffee machine helps to survive through deadlines.

You can use furniture to fill our rooms.

Also, you can use interface components to fill pages.

Pages are built with this pieces like houses are build with blocks. So, let's
call them just that, `blocks`.

## Block

A block is an independent interface piece that preserves a design point and some
functionality. Anything that can be taken as a solid piece and can be put into a
page is an interface block.

To operate the blocks, it's good to name them. Here there are a `Menu`, a
`Calendar` control, a `Footer`, a `Tabbed pane`, a `Dropdown` and a `Search`
blocks.

Futhermore, some blocks are large. They usually preserve other blocks. But they
still are solid independent pieces.

Here you can see the `Header` block that contains some others.

### Block HTML representation

*Indeed, behind the scenes there are our dear HTML and CSS.*

Each block is represented by a piece of HTML markup. To style the block you can
write the CSS rules, as usual.

`Menu` block is an `ul` tag and its content.

````js
    <ul class="menu">
        <li><a href="/new">New titiles</a></li>
        <li><a href="/soon">Coming soon</a></li>
        <li><a href="/best">Bestsellers</a></li>
        ...
````

The same works for the `Search` block, that is represented by `div` tag with
some content.

````js
    <div class="search">
        <input type="text" name="search" value="..."/>
        <input type="button" name="sbmt" value="Search"/>
    </div>
````

The last example is the `Tabbed Pane` block, which is also a combination of HTML
and CSS.

````js
    <div class="tabbed-pane">
        <ul>
            <li>Bestsellers</li><li>...</li>
        </ul>
        <div>
           The Casual Vacancy, J.K. Rowling
        </div>
     </div>
````

## Independent CSS blocks
But in order to build pages with blocks, we developers should be sure that these
interface pieces can be put into any place on a page. This can be possible only
if blocks are `independent`.

Block independency means the following.

A block must not be affected by its ancestors, and in its turn must
not affect the descendants.

Regardless of where this block is placed.

When filling a page with blocks, we developers, shouldn't care where exactly
each block is placed. You just define a set of blocks with the appropriate order.
And that's enough for getting a complete functional page.

````js
    <html>
        <head>..</head>
        <body>

            <div class="head">
                <div class="logo">...</div>
                <ul class="menu">...</ul>
                <div class="search">...</div>
            </div>

            <div class="layout">...</div>

            <div class="foot">...</div>

        </body>
    </html>
````

But, of course, this maybe possible only due to some architectural requirements
to each block. Let us now see what these requirements are. For this let's have a
look at what situations can cause block affection and how to prevent them
beforehand.

### Repeating
The first is repeating blocks.

The same block can appear on the page. For example, one more `Menu` block can be
placed into the `Foot` block.

Since now the `Menu` block is not a unique within a page. Because of that you
cannot use `id` selectors to match the CSS rules to it, this would be invalid.

So,

To apply CSS to a block, you should use classname selectors.

**wrong**

````js
    <ul id="menu">
        ...

    #menu {
        ...
````

**right**

````js
    <ul class="menu">
        ...

    .menu {
    ...
````

This rule is correct for any block.

Even if you think *now* that the block is unique within a page, this can be
changed in the future. So, the best practice is to avoid id selectors at all and
use classes.

### Moving within a Page

The next that can happen with a block is its movement within a page.

As you can see in the video, the `Tabbed Pane` block was moved to he right side
of the page and immediately got broken since it has new ancestors, new parent
DOM nodes now.

This is that must not happen. You should guarantee that a block will work
correctly in any place on the page.

Actually you can ensure this only by *avoiding cascade in CSS*.

Such a recomendation sounds provocative. But anyway this is reasonable. Now
let's see why.

Cascade is a kind of relations between objects. A cascade rule says that one
object depends on another. It is a connection that can give some benefits.

But you should have a control over all those connections. If not, this may break
all.

Trying to fix, developers usually add even more connections into the system. That
seems to work at first. But each addition just increase uncontrolable mess.

The more cascade code you bring into the service, we more is risk of future damages.

So, you should use cascade only when it's really necessary.

I'll show below the situation when cascade is possible. But in general the
suggestion is to avoid it.

### Moving within a Site

The next block's adventure is to be moved from page to page.

The already familiar `Tabbed pane` block can be widely adopted. We can use it on
many pages. Of course, on a different page it has another parent block. As I've
said above, you should guarantee that it works correctly regardless of its
environment. This is what you achieve due to avoiding cascade.

Again, even if a block *now* is a single one within a whole site, that does not
mean it should depend on its surroundings.

The recommendation about avoiding cascade works for all the blocks.

#### Pages are Sets of Blocks
The other point is that when you are developing and maintaining, the block set of
every page changes.

We, developers, should think about keeping associated CSS in the actual state.
So that if a block was removed from a page, we should remove its CSS code. Also,
if a block was added to a page, we should ensure its CSS is linked there.

That is not a problem for sites of 2-3 pages since we can keep all the stuff in
a single one CSS file.

But usually life is not that easy; there are several pages that are different but
still have some common design solutions. At least the `Header` block is included in
all the pages.

So, developers usually place the common stuff into the `common.css` file.
Everything else is distributed per pages.

But let us look a bit closer to this practice.

As you see in the picture, the `Header` block contains the `Search` block. This
design solution seems to be invariable within the whole site.

But not. The page providing advanced search form doesn't have this `Search` block
in the `Header`.

So, should we include the `Search` block code into `common.css` file? Seems like
shouldn't. Well, should we copy-paste it for all the other pages? Again, no.

Moreover, this is just a simple example. In the real life the variety of
interface object combinations indeed can be huge. Usually it is very hard to
define the common stuff.

On the other hand, copy paste is even worse.

So, there should be a way out.

What about turning these drawn sets of blocks into code?

You can store CSS code for every block separately, each in a file with a
corresponding name.

    blocks/
        header.css
        menu.css
        button.css
        tabbed-pane.css
        logo.css
        footer.css

So that, CSS for the `Menu` block is in the `menu.css` file, CSS for `Tabbed
Pane` block is the `tabbed-pane.css` file and so on.

Then, you can pack the CSS files for the pages with these blocks using an
`import` keyword.

````js
    @import url(blocks/header.css);
    @import url(blocks/menu.css);
    @import url(blocks/tabbed-pane.css);
    @import url(blocks/text.css);
    @import url(blocks/logo.css);
    @importurl(blocks/footer.css);
````

That enables you to take only what's necessary for a page.

As a result there is a block stack of our project, stored in a special folder.
And some pages that use these blocks.

Looks cool, but

## Inside a Block
So, let's have a look what is inside our blocks.

The `Menu` block is going to be the first example.

````js
    <ul class="menu">
        <li><a href="/new">New titles</a></li>
        <li><a href="/soon">Coming soon</a></li>
        <li><a href="/best">Bestsellers</a></li>
        ...
    </ul>
````

It's represented by `ul` tag and has some `li` children for the items. Also, the
`ul` tag is marked with a CSS class, so that you can apply the rules to it.

But the question is "What to do with the items?"

The wide-spreaded solution is to write the CSS selector similar to the following.

````js
    .menu li
    {
        list-style: none;
        display: inline-block;
        padding: 0 0.5em;
    }
````

As you can see, cascade is used here. It seems to work right at first, because
all the reasons I listed against cascade are not for this situation. `li` tags
are always inside their `ul` parent. So, nothing bad should happen.

But even inside such a small interface piece like a menu item there can be a lot
of HTML markup in the future.

Here you can see that a `Dropdown` block with its own list was placed into the
menu item and immediately got broken because of this CSS instruction affects it.

We got the long menu sausage instead of a nice dropdown.

As you can see, except of avoiding cascade there appears even more specific
rule.

You should not use tag selectors.

The additional explanation why it is a bad practice to use tag selectors can be
easily found in the Internet.

The style system matches rules by
starting with the key selector, then moving to the left (looking for any
ancestors in the rule's selector).

Further information can be found in [Davis Hyatt's
article](http://mzl.la/UuwZql), from Mozilla.

However we still need a solution to style menu items inside the `Menu` block.

##Element
First, let's clarify a definition and call the things inside a block — `elements`.

This is a clear picture of what elements are.

As you can see, elements are non-independent pieces of an interface. They make no
sense on their own, but are to be used within their parent block.

For example, the `Search` block has an `input` element and a `button` element.

The `Tabbed Pane` block has 2 `tab` elements (and can have more if necessary)
and the `pane` element to keep its content.

Styling elements you should think about them as self-reliant entities.

To apply CSS rules to the elements you will need to mark them with classes.

In turn, to avoid cascade, it's necessary to prefix these classes with the block
name.

````js
    <ul class="menu">
        <li class="menu__item"><a href="/">Index</a></li>
        <li class="menu__item"><a href="/new">New</a></li>
        <li class="menu__item"><a href="/offer">Special offer</a></li>
        <li class="menu__item"><a href="/shipping">Shipping</a></li>
    </ul>
````

````js
    .menu__item
    {
        list-style: none;
        display: inline-block;
        padding: 0 0.5em;
    }
````

You can see here that CSS class for a menu item consists of block name, which is
`menu`, element name, which is `item` and a group of separation symbols.

We, at Yandex, use 2 underscores for separation. But that's optional. You can
choose another symbol or a group of symbols.

````js
    .block__element
    .block-element
    .block--element
````

If you don't like 2 underscores, maybe you'll be pleased with 3 ;-)

###Optional elements
So far so good, a block can be different from page to page.

The difference you can see in the slide is that it comprises different sets of
elements. So that, elements are optional. This means you should be able to take
CSS code for the elements we use.

Similar to blocks, elements can be stored separately.

````js
    blocks/

        search.css
        search__checkbox.css
        search__autocomplete.css

        tabbed-pane.css
        tabbed-pane__tab.css
        tabbed-pane__pane.css

        menu.css
        menu__item.css

        book.css
        book__title.css
        book__image.css
````

That enables you to take element code only if you want. If not, you just won't
write the import instruction linking it to your page.

##Modifier
Now to the last notion, a `modifier`.

Again, the same block sometimes can look slightly different. Here it is not
because of optional elements but because of its own design distinctions.

Of course, it is always possible to implement all these tabbed panes as diverse
blocks. But that would be copy paste which we we can't abide.

The way out is to equip a block with an additional CSS class to provide changes.
Such an addition is called a modifier.

````js
    <div class="tabbed-pane tabbed-pane_theme_blue">
        <ul>
            <li class="tabbed-pane__tab">Tab 1</li>
            <li class="tabbed-pane__tab">Tab 2</li>
        </ul>
        <div class="tabbed-pane__pane">
            ...
        </div>
    </div>
````

Remember, we were wise enough to use classes. So, we can add to a block DOM node
as many modifiers as we need.

````js
    <div class="tabbed-pane
                tabbed-pane_theme_blue
                tabbed-pane_direction_bottom">
        ...
    </div>

    <input class="button
                  button_theme_black
                  button_size_l" ... />
````

You can use different modifiers to change different properties. For example, the
`theme` modifier can change block's background color and the `size` modifier
fixes all the dimensions of the block.

**block-name_mod-name_mod-val**

A modifier is a key-value combination, it consists of modifier name, modifier
value and is prefixed with block name.

````js
    tabbed-pane_theme_blue
    tabbed-pane_theme_white

    tabbed-pane_size_s
    tabbed-pane_size_l

    button_size_s
    button_size_l
````

Indeed, modifiers are optional. You almost never will need to link to a page all
the block modifiers since blocks are rarely used in all their modifications
within one page.

So, similar to optional elements, you can detach their CSS code into their own
files.

````js
    blocks/
        tabbed-pane.css
        tabbed-pane__tab.css
        tabbed-pane__pane.css
        tabbed-pane_theme_blue.css
        tabbed-pane_theme_black.css
        tabbed-pane_direction_bottom.css
````

When building a page CSS file of blocks, you can take only those modifiers which
it needs.

### Modifying elements
Elements can be modified in the same way.

The famous examples of modified elements are active tabs and menu items. They
look a bit different from their friends.

To deliver design changes to an active tab, you need to add a modifier to an
element. Similar to what we was doing for blocks.

````js
    <div class="tabbed-pane">
        <span class="
            tabbed-pane__tab
            tabbed-pane__tab_state_current">...</span>
    </div>
````

### Block Modifier DOES Affect Element
Now I'm going to show you where cascade is posible.

You can see a modified block here. It has a blue theme. Of course, when having a
blue theme the block should guarantee that its elements will work correctly. In
this situation you allow the block affect its elements.

````js
    .tabbed-pane_theme_blue
    .tabbed-pane__tab
    {
       background-color: #9CF;
    }
````

Here cascade is possible because the tabs' appearance DOES depend on block's
modifier.

*************
And just to wrap up, to make your blocks independent, be sure that

 * a block has its "name"
   - no "id" but "classname" selectors
 * avoid cascade
 * no "tag" selectors

##Block File Structure
All the previously shown examples used flat variant when CSS files for blocks,
elements and modifiers are placed into one folder `blocks`.

````js
    blocks/

        tabbed-pane.css
        tabbed-pane__tab.css
        tabbed-pane__pane.css
        tabbed-pane_theme_blue.css
        tabbed-pane_theme_black.css
        tabbed-pane_size_l.css
        tabbed-pane_size_s.css

        menu.css
        menu__item.css
        menu_size_l.css
        menu_size_s.css

        logo.css

        search.css
        search__checkbox.css
        search__autocomplete.css
````

That works for not very large projects and not very complicated blocks.

If you expect many blocks with elements and modifiers, it's good to contain all
the files related to a block in a block folder.

````js
    blocks/

        tabbed-pane/
            tabbed-pane.css
            tabbed-pane__tab.css
            tabbed-pane__pane.css
            tabbed-pane_theme_blue.css
            tabbed-pane_theme_black.css
            tabbed-pane_size_l.css
            tabbed-pane_size_s.css

        logo/
            logo.css

        menu/
            menu.css
            menu__item.css
            menu_size_l.css
            menu_size_s.css

        search/
            search.css
            search__checkbox.css
            search__autocomplete.css
````

Less mess, and also it's much easier to copy block files from project to project.

We, at Yandex, use the most detailed structure with internal folders for
elements and modifiers.

````js
    blocks/

        tabbed-pane/
            __tab/
                _state/
                    tabbed-pane__tab_state_current.css
                tabbed-pane__tab.css
            __pane/
                tabbed-pane__pane.css
            _theme/
                tabbed-pane_theme_blue.css
                tabbed-pane_theme_black.css
            tabbed-pane.css
````

It is not obligatory, but just works for our case.

Now, before proceeding to the next section, let us sum up.

 * First, any interface is a set of blocks, which can be combined in different
ways, can be placed one into another, can change their parent block. And nothing
bad should happen since the blocks are independent.
 * Also, all the nested tags in a block are elements.
 * And finally, both blocks and elements can be modified.

## BEM

Now, that the three terms are introduced, I am happy to present you BEM methodology.
You've just learnt its parts related to independent CSS blocks.

Furthermore, BEM brings some other interesting solutions.

 * First, BEM is a methodology. It's a way of thinking when developing. It provides
us with data domain applicable for all the technologies.
 * Besides, BEM is a toolkit automating your work.
 * Finally, BEM is a range of reusable code libraries, making you to develop
 * faster and better.

Now let's have a look at all these opportunities in a little more detail.

### CSS for IE
First, I'd like to show how we deal with our bosom friend, the IE browser.

It is possible to link an additional CSS file to a page, especially for IE.
Using conditional comments you make other browsers ignore this file. So that,
there we can write fixes for IE only.

````js
    <html>
        <head>
            <!--[if gt IE 7]><!-->
                <link rel="stylesheet" href="index.css">
            <!--<![endif]-->
            <!--[if lt IE 8]>
                <link rel=stylesheet href="index.ie.css">
            <![endif]-->
        </head>
        ...
````

Inside the `ie.css` file you import the general CSS file for the page.

````js
    @import url(index.css);
    @import url(blocks/menu/menu.ie.css);
    @import url(blocks/button/button.ie.css);
    @import url(blocks/footer/footer.ie.css);
````

Then, you can redefine CSS that doesn't work correctly for every piece of
interface. It's logical to do it separately for each block.

Blocks that need special IE hacks are equipped with additional `ie.css` files.
If all the block files are under the block folder, we can just place one more
file in it.

````js
    blocks/

        tabbed-pane/
            tabbed-pane.css
            tabbed-pane.ie.css
            ...

        menu/
            menu.css
            menu.ie.css
````

The same works for elements and modifiers.

````js
    blocks/

        tabbed-pane/
            tabbed-pane.css
            tabbed-pane.ie.css
            tabbed-pane__item.css
            tabbed-pane__item.ie.css
            tabbed-pane_theme_blue.css
            tabbed-pane_theme_blue.ie.css with
````

So, a block folder encapsulates all the CSS needed. Using the project block
stack we can assemble CSS files for pages, both the general one and for IE.

## JavaScript
HTML/CSS dummy is not a functional web application yet. But implementing some
JavaScript logic we can paint it with colours.

We should code that the `Tabbed Pane` block reacts on leftclick.

The `Dropdown` block functionality is that it is hidden when a page is just
loaded. But if a user makes clicks with the left mouse button on its switcher,
the block shows.

The `Dropdown` also can be smart enough to calculate its direction according to its
place on a page. In the picture the second `Dropdown` block opens up since it's
too close to the bottom.

This needs JavaScript logic which you have to provide for a page. Pages are
usually supplied with JavaScript logic by linking a `.js` file to it.

### Sets of Block in JavaScript
Again, for small projects all the magic can fit comfortably into a single one
JavaScript file.

````js
    <!DOCTYPE html>
    <html>
        <head>
            <link rel=stylesheet href="index.css"/>
            <script type="text/javascript" src="all.js"></script>
        </head>
        ...
````

But usually we have different functionality for different pages. So that similar
to CSS we a have separate JS file for every page.

````js
    <!DOCTYPE html>
    <html>
        <head>
            <link rel=stylesheet href="index.css"/>
            <script type="text/javascript" src="index.js"></script>
        </head>
        ...
````

Again, block set of a page can be changed and you need to ensure that you link
corresponding JavaScript.

Similar to CSS for blocks, you can detach a separate js file for every block and
store it under the block folder.

````js
    blocks/
        menu/
            menu.css
            menu.js
        dropdown/
            dropdown.css
            dropdown.js
        tabbed-pane/
            tabbed-pane.css
            tabbed-pane.js
````

Inside the `menu.js` file there is a piece of logic related to the `Menu`. The
same for the `Tabbed Pane`.

Using these pieces of logic you can build JavaScript file for a page similar to
what you've done with CSS before.

````js
    borschik:include:blocks/menu/menu.js
    borschik:include:blocks/tabbed-pane/tabbed-pane.js
    ...
````

Each line in the file refers to a particular block.

##CSS and JavaScript flattening with borschik

Don't be confused with an unfamiliar `include` instruction. Of course, we are
not going to supply a browser with such a strange file but flatten each include.

````js
    /* Menu block begins */
    (function($){
        $('.menu__item').on('click', function(e) {
            $(this).toggleClass('menu__item_state_current');
        });
    })(jQuery)
````

Here you can see here that including line for the menu turned into the content
of the file.

You can do such inlining magic automatically with the tool called
[borschik](https://github.com/veged/borschik).

Besides flattening JavaScript, it does the same with CSS files of imports.

You can work with imports when developing, but for production it's better to
decrease the amount of CSS files. Each CSS `@import` causes an HTTP request making
a browser to load many files.

````js
    @import url(blocks/header.css);
    @import url(blocks/menu.css);
    ...
````

Using `borschik` to prepare a project for production deployment you can turn all
the imports into relevant CSS content.

````js
    .header {
        ...
    }
    .menu {
        ...
    }
````

This is very important that `borschik` works correctly with relative paths in CSS.
So, it's not just stupid inlining.

**blocks/menu/menu.css**

````js
    .menu {

        background: url(menu__bg.png);

    }
````

**pages/index.css**

````js
    @import url(blocks/menu/menu.css);
````

**pages/_index.css**

````js
    .menu {

        background: url(../blocks/menu/menu__bg.png);

    }
````

## Building Page Files

The page which a browser gets is not one piece of code. As you've already seen,
it is a bunch of at least 4 files, which are HTML, 2 CSS files and JavaScript.

When the page is under development or is maintained, set of its blocks can
change. If a block was included into the set or removed from it, we are to
change all the files.

Actually it is a monkey job that definitely can be automated.

The images shows us what are the blocks on the page and which ones contain others.

We got this information with a visual language the picture provides. But the
same can be described in text. Any nesting format works for it.

````js
    <b:page>
        <b:head>
            <b:logo/>
            <b:search>
                <e:input/>
                <e:button/>
            </b-search>
            <b:menu>
                <e:item>Home</e:item>
                <e:item>Contacts</e:item>
                ...
````

In Yandex it used to use XML, but now it's JSON.

````js
    {
        block: 'page',
        content: [
            {
                block: head,
                content: [
                    { block: 'logo' },
                    {
                        block: 'search',
                        ...
````

This page declaration is called `BEM tree` by analogy to DOM tree.

The format describes what are the blocks on a page, preserves their nesting
structure, elements and modifiers which blocks are using.

Such a format can be parsed with a special tools and turned into the CSS and
JavaScript files automatically.

The `BEM tree` can be turned into all the necessary static files. And if you need
changes, you can fix `BEM tree`, run transformation process again and get updated
files.

These transformations are possible with a toolkit called [BEM
tools](http://bem.info/tools/bem/). It's open sourced and hosted on GitHub,
where you can find its installing instructions and a full description.

It already supports many fashionable technologies you might want to use, such as
SASS, LESS, CoffeeScript. You are free to write code for your blocks with them
and then build it into pages.

````js
    blocks/

        menu/
            menu.sass
            menu.less
            menu.coffee

        tabbed-pane/
            tabbed-pane.sass
            tabbed-pane.coffee

    pages/

        index.html
        index.sass -> index.css
        index.coffee -> index.js
````

Also it allows extensions. So, if your project needs a specific technology, you
can a bit tune building instructions to teach the tools how to work with it.

Moreover, there is no strict requirement to a naming convention and a file
structure of your block stack. You are free to intent your own and configure
tools to take block code from the right folders or files.

## BEM is Multi-lingual

I'd like to highlight that BEM methodology is multi technological. You can
divide any technology into blocks and then build pages.

For example, equip blocks with their Markdown description and build
documentation site for your project block stack automatically.

````js
    blocks/

        menu/
            tabbed-pane.css
            tabbed-pane.js
            tabbed-pane.md
````

This is what we've done at Yandex for our internal block library.

Also, you can produce HTML output for blocks with templates. And templates are a
block technology as well.

````js
    blocks/

        menu/
            tabbed-pane.css
            tabbed-pane.js
            tabbed-pane.md
            tabbed-pane.xsl
````

For our internal library we also used to use XSL asa templating solution. But
not long ago we struggled with XSL for speed and came up with our own
JavaScript-based template engine, called `BEMHTML`.

````js
    blocks/

        menu/
            tabbed-pane.css
            tabbed-pane.js
            tabbed-pane.md
            tabbed-pane.bemhtml
````

When that happend, we were just to add one more technology into already existing
blocks. That was very easy.

## BEMHTML

BTW, `BEMHML` is a pseudo language which can be compiled into ugly but efficient
JavaScript.

We, at Yandex, are fans of declarative programming, and borrowed from XSL all
it's declarative feature and implemented it with JavaScript speed.

The result can be run on both client or server size. Sometimes we produce HTML
output on server under Node.js and sometimes directly in a browser.

If you are insriped, you can check out [BEMHTML
reference](https://raw.github.com/bem/bem-bl/0.3/blocks-common/i-bem/__html/i-bem__html.wiki).

However, the document is in Russian only, so you might need to use
http://translate.yandex.com/. Official document's translation is still in
progress.

## Libraries
BEM methodology enables you to create reusable code libraries. That, in turn,
allows to develop faster and better.

We, here at Yandex, have a bunch of our in-house BEM-based libraries helping us
to build a new Yandex-style web service much faster than from the scratch and
making maintaining process easier.

When we started to open source our magic stuff, a small part of the internal
library was turned into [bem-bl](http://bem.github.com/bem-bl/index.en.html).

`bem-bl` stands for `BEM block library` and provides some common blocks for
building web interfaces.

All the available blocks are represented at the [bem-bl documentation web
site](http://bem.github.com/bem-bl/index.en.html).

Each block is represented by a documentation page where you can find its
description and some examples. Significant that all these examples are alive.
They are not just screenshots of interface pieces, but iframes showing real
pages with blocks.

Using the block page you can try how the block works in your browser and then
proceed to the code in order to see how to use it.

Also, you can explore block code since they all are in the [GitHub
repository](https://github.com/bem/bem-bl).

Such exploration helps when you need to create your own block library.

### Examples of BEM Libraries

Here there are some libraries implemented with BEM:

* [Bootsrap BL](https://github.com/tadatuta/bootstrap-bl)

The famous bootstrap component stack structured like a BEM library so that BEM
tools can work with it.
* [jQueryUI BL](https://github.com/narqo/jqueryui-bl)

A set of jQuery-UI components turned into a block library. If you are used to
jQuery-UI, you can still use it but with the nice BEM stack.
* [Modernizir BL](https://github.com/narqo/modernizr-bl)

a small repository that represents the Modernizr library, which many of you I'm
sure are familiar with, with BEM terms.

## How to Try?
There is a project skeleton hosted on GitHub,
[bem-project-stub](https://github.com/bem/project-stub).

This is a repository that can be a base for your own project using `bem-bl`,
other necessary libraries and, of course, your own blocks. It's README gives all
the explanations.

So, this is a cool opportunity to touch BEM stack.

### BEM Satellite Development Tools

Besides, BEM team also produces many very nice development tools.

[borschik](https://github.com/veged/borschik) has already been introduced.

Also, you might be interested in [CSSO](http://bem.info/tools/csso/), which is
CSS optimizer unlike others. It does usual minification, but what is more,
preforms structural optimizations, which no one of existing optimizers can do.

**before**

````js
    .test1 {
        border: none;
        background-color: red;
    }

    .test2 {
        border: none
    }

    .test3 {
        background-color: #FF000;
    }
````

**after**

````js
    .test1, .test2 {
        border: none
    }

    .test1, .test3 {
        background-color: #F00;
    }
````

These two small pieces of code give a taste how smart CSSO is. Indeed the full
list of the transformations it makes on CSS cannot be listed because of it's
really huge. But you can find them all with the link http://bem.info/tools/csso/.

One more optimizer, called [SVGO](https://github.com/svg/svgo), cleans SVG files
from many useless information which different graphic editors leave inside.

### Upshort

So, BEM is

 - A methodology about how to code web projects;
 - A toolkit to automate development and optimize production code, and
 - Libraries helping to develop faster and better.

Please address your questions to the comminuty asking in [BEM Facebook
group](http://www.facebook.com/groups/209713935765634/) or in Twitter
[@bem_tw](https://twitter.com/bem_tw).

This information is also available as a talk "[BEM. What you can borrow from Yandex frontend dev](https://vimeo.com/53219242)" given at [WebConf Riga](http://webconf.lv/) at 10th November 2012.


text:
package com.artemis;

/**
 * Placeholder for utility classes that depend on SuperMapper.
 *
 * Serves as a placeholder for testing fluid utility classes. This file is never deployed with the utility classes,
 * instead {@link com.artemis.FluidGenerator} generates a user specific version. See artemis-fluid-core pom for
 * build details.
 *
 * @author Daan van Yperen
 */
public class SuperMapper {
}


text:
@implementation CTProfileMiscSectionController

- (instancetype)init{
    self = [super init];
    if (self) {
        [self registerAdapter:[CTIconCellAdapter new] forItemClass:[NSDictionary class]];
    }
    return self;
}

- (CGFloat)dataViewController:(AKDataViewController *)dataViewController item:(id<NSObject>)module heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [super dataViewController:dataViewController item:module heightForRowAtIndexPath:indexPath];
}

- (AKTableViewCell *)dataViewController:(AKDataViewController *)dataViewController item:(id<NSObject>)item cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [super dataViewController:dataViewController item:item cellForRowAtIndexPath:indexPath];
}

@end


text:
package org.elasticsearch.join.mapper;

import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MapperException;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.SourceToParse;
import org.elasticsearch.join.ParentJoinPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESSingleNodeTestCase;

import java.util.Collection;
import java.util.Collections;

import static org.hamcrest.Matchers.containsString;

public class ParentJoinFieldMapperTests extends ESSingleNodeTestCase {
    @Override
    protected Collection<Class<? extends Plugin>> getPlugins() {
        return Collections.singletonList(ParentJoinPlugin.class);
    }

    public void testSingleLevel() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
            .startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .field("parent", "child")
                    .endObject()
                .endObject()
            .endObject()
            .endObject());
        IndexService service = createIndex("test");
        DocumentMapper docMapper = service.mapperService().merge("type", new CompressedXContent(mapping),
            MapperService.MergeReason.MAPPING_UPDATE);
        assertTrue(docMapper.mappers().getMapper("join_field") == ParentJoinFieldMapper.getMapper(service.mapperService()));

        // Doc without join
        ParsedDocument doc = docMapper.parse(SourceToParse.source("test", "type", "0",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject().endObject()), XContentType.JSON));
        assertNull(doc.rootDoc().getBinaryValue("join_field"));

        // Doc parent
        doc = docMapper.parse(SourceToParse.source("test", "type", "1",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                .field("join_field", "parent")
                .endObject()), XContentType.JSON));
        assertEquals("1", doc.rootDoc().getBinaryValue("join_field#parent").utf8ToString());
        assertEquals("parent", doc.rootDoc().getBinaryValue("join_field").utf8ToString());

        // Doc child
        doc = docMapper.parse(SourceToParse.source("test", "type", "2",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                .startObject("join_field")
                    .field("name", "child")
                    .field("parent", "1")
                .endObject()
                .endObject()), XContentType.JSON).routing("1"));
        assertEquals("1", doc.rootDoc().getBinaryValue("join_field#parent").utf8ToString());
        assertEquals("child", doc.rootDoc().getBinaryValue("join_field").utf8ToString());

        // Unkwnown join name
        MapperException exc = expectThrows(MapperParsingException.class,
            () -> docMapper.parse(SourceToParse.source("test", "type", "1",
                BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                    .field("join_field", "unknown")
                    .endObject()), XContentType.JSON)));
        assertThat(exc.getRootCause().getMessage(), containsString("unknown join name [unknown] for field [join_field]"));
    }

    public void testParentIdSpecifiedAsNumber() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
            .startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                        .startObject("relations")
                            .field("parent", "child")
                        .endObject()
                    .endObject()
                .endObject()
            .endObject());
        IndexService service = createIndex("test");
        DocumentMapper docMapper = service.mapperService().merge("type", new CompressedXContent(mapping),
            MapperService.MergeReason.MAPPING_UPDATE);
        ParsedDocument doc = docMapper.parse(SourceToParse.source("test", "type", "2",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                .startObject("join_field")
                .field("name", "child")
                .field("parent", 1)
                .endObject()
                .endObject()), XContentType.JSON).routing("1"));
        assertEquals("1", doc.rootDoc().getBinaryValue("join_field#parent").utf8ToString());
        assertEquals("child", doc.rootDoc().getBinaryValue("join_field").utf8ToString());
        doc = docMapper.parse(SourceToParse.source("test", "type", "2",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                .startObject("join_field")
                .field("name", "child")
                .field("parent", 1.0)
                .endObject()
                .endObject()), XContentType.JSON).routing("1"));
        assertEquals("1.0", doc.rootDoc().getBinaryValue("join_field#parent").utf8ToString());
        assertEquals("child", doc.rootDoc().getBinaryValue("join_field").utf8ToString());
    }

    public void testMultipleLevels() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
            .startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .field("parent", "child")
                        .field("child", "grand_child")
                    .endObject()
                .endObject()
            .endObject()
            .endObject());
        IndexService service = createIndex("test");
        DocumentMapper docMapper = service.mapperService().merge("type", new CompressedXContent(mapping),
            MapperService.MergeReason.MAPPING_UPDATE);
        assertTrue(docMapper.mappers().getMapper("join_field") == ParentJoinFieldMapper.getMapper(service.mapperService()));

        // Doc without join
        ParsedDocument doc = docMapper.parse(SourceToParse.source("test", "type", "0",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject().endObject()), XContentType.JSON));
        assertNull(doc.rootDoc().getBinaryValue("join_field"));

        // Doc parent
        doc = docMapper.parse(SourceToParse.source("test", "type", "1",
            BytesReference.bytes(XContentFactory.jsonBuilder()
                .startObject()
                    .field("join_field", "parent")
                .endObject()), XContentType.JSON));
        assertEquals("1", doc.rootDoc().getBinaryValue("join_field#parent").utf8ToString());
        assertEquals("parent", doc.rootDoc().getBinaryValue("join_field").utf8ToString());

        // Doc child
        doc = docMapper.parse(SourceToParse.source("test", "type", "2",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                .startObject("join_field")
                    .field("name", "child")
                    .field("parent", "1")
                .endObject()
                .endObject()), XContentType.JSON).routing("1"));
        assertEquals("1", doc.rootDoc().getBinaryValue("join_field#parent").utf8ToString());
        assertEquals("2", doc.rootDoc().getBinaryValue("join_field#child").utf8ToString());
        assertEquals("child", doc.rootDoc().getBinaryValue("join_field").utf8ToString());

        // Doc child missing parent
        MapperException exc = expectThrows(MapperParsingException.class,
            () -> docMapper.parse(SourceToParse.source("test", "type", "2",
                BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                    .field("join_field", "child")
                    .endObject()), XContentType.JSON).routing("1")));
        assertThat(exc.getRootCause().getMessage(), containsString("[parent] is missing for join field [join_field]"));

        // Doc child missing routing
        exc = expectThrows(MapperParsingException.class,
            () -> docMapper.parse(SourceToParse.source("test", "type", "2",
                BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                    .startObject("join_field")
                    .field("name", "child")
                    .field("parent", "1")
                    .endObject()
                    .endObject()), XContentType.JSON)));
        assertThat(exc.getRootCause().getMessage(), containsString("[routing] is missing for join field [join_field]"));

        // Doc grand_child
        doc = docMapper.parse(SourceToParse.source("test", "type", "3",
            BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                .startObject("join_field")
                    .field("name", "grand_child")
                    .field("parent", "2")
                .endObject()
                .endObject()), XContentType.JSON).routing("1"));
        assertEquals("2", doc.rootDoc().getBinaryValue("join_field#child").utf8ToString());
        assertEquals("grand_child", doc.rootDoc().getBinaryValue("join_field").utf8ToString());

        // Unkwnown join name
        exc = expectThrows(MapperParsingException.class,
            () -> docMapper.parse(SourceToParse.source("test", "type", "1",
                BytesReference.bytes(XContentFactory.jsonBuilder().startObject()
                    .field("join_field", "unknown")
                    .endObject()), XContentType.JSON)));
        assertThat(exc.getRootCause().getMessage(), containsString("unknown join name [unknown] for field [join_field]"));
    }

    public void testUpdateRelations() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
            .startObject("join_field")
                .field("type", "join")
                .startObject("relations")
                    .field("parent", "child")
                    .array("child", "grand_child1", "grand_child2")
                .endObject()
            .endObject()
            .endObject().endObject());
        IndexService indexService = createIndex("test");
        DocumentMapper docMapper = indexService.mapperService().merge("type", new CompressedXContent(mapping),
            MapperService.MergeReason.MAPPING_UPDATE);
        assertTrue(docMapper.mappers().getMapper("join_field") == ParentJoinFieldMapper.getMapper(indexService.mapperService()));

        {
            final String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .array("child", "grand_child1", "grand_child2")
                    .endObject()
                .endObject()
                .endObject().endObject());
            IllegalStateException exc = expectThrows(IllegalStateException.class,
                () -> indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
                    MapperService.MergeReason.MAPPING_UPDATE));
            assertThat(exc.getMessage(), containsString("cannot remove parent [parent] in join field [join_field]"));
        }

        {
            final String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .field("parent", "child")
                        .field("child", "grand_child1")
                    .endObject()
                .endObject()
                .endObject().endObject());
            IllegalStateException exc = expectThrows(IllegalStateException.class,
                () -> indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
                    MapperService.MergeReason.MAPPING_UPDATE));
            assertThat(exc.getMessage(), containsString("cannot remove child [grand_child2] in join field [join_field]"));
        }

        {
            final String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .field("uber_parent", "parent")
                        .field("parent", "child")
                        .array("child", "grand_child1", "grand_child2")
                    .endObject()
                .endObject()
                .endObject().endObject());
            IllegalStateException exc = expectThrows(IllegalStateException.class,
                () -> indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
                    MapperService.MergeReason.MAPPING_UPDATE));
            assertThat(exc.getMessage(), containsString("cannot create child [parent] from an existing parent"));
        }

        {
            final String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .field("parent", "child")
                        .array("child", "grand_child1", "grand_child2")
                        .field("grand_child2", "grand_grand_child")
                    .endObject()
                .endObject()
                .endObject().endObject());
            IllegalStateException exc = expectThrows(IllegalStateException.class,
                () -> indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
                    MapperService.MergeReason.MAPPING_UPDATE));
            assertThat(exc.getMessage(), containsString("cannot create parent [grand_child2] from an existing child]"));
        }

        {
            final String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .array("parent", "child", "child2")
                        .array("child", "grand_child1", "grand_child2")
                    .endObject()
                .endObject()
                .endObject().endObject());
            docMapper = indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
                MapperService.MergeReason.MAPPING_UPDATE);
            assertTrue(docMapper.mappers().getMapper("join_field") == ParentJoinFieldMapper.getMapper(indexService.mapperService()));
            ParentJoinFieldMapper mapper = ParentJoinFieldMapper.getMapper(indexService.mapperService());
            assertTrue(mapper.hasChild("child2"));
            assertFalse(mapper.hasParent("child2"));
            assertTrue(mapper.hasChild("grand_child2"));
            assertFalse(mapper.hasParent("grand_child2"));
        }

        {
            final String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .array("parent", "child", "child2")
                        .array("child", "grand_child1", "grand_child2")
                        .array("other", "child_other1", "child_other2")
                    .endObject()
                .endObject()
                .endObject().endObject());
            docMapper = indexService.mapperService().merge("type", new CompressedXContent(updateMapping),
                MapperService.MergeReason.MAPPING_UPDATE);
            assertTrue(docMapper.mappers().getMapper("join_field") == ParentJoinFieldMapper.getMapper(indexService.mapperService()));
            ParentJoinFieldMapper mapper = ParentJoinFieldMapper.getMapper(indexService.mapperService());
            assertTrue(mapper.hasParent("other"));
            assertFalse(mapper.hasChild("other"));
            assertTrue(mapper.hasChild("child_other1"));
            assertFalse(mapper.hasParent("child_other1"));
            assertTrue(mapper.hasChild("child_other2"));
            assertFalse(mapper.hasParent("child_other2"));
        }
    }

    public void testInvalidJoinFieldInsideObject() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
            .startObject("object")
                .startObject("properties")
                    .startObject("join_field")
                        .field("type", "join")
                        .startObject("relations")
                            .field("parent", "child")
                        .endObject()
                    .endObject()
                .endObject()
            .endObject()
            .endObject().endObject());
        IndexService indexService = createIndex("test");
        MapperParsingException exc = expectThrows(MapperParsingException.class,
            () -> indexService.mapperService().merge("type", new CompressedXContent(mapping),
                MapperService.MergeReason.MAPPING_UPDATE));
        assertThat(exc.getRootCause().getMessage(),
            containsString("join field [object.join_field] cannot be added inside an object or in a multi-field"));
    }

    public void testInvalidJoinFieldInsideMultiFields() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("properties")
            .startObject("number")
                .field("type", "integer")
                .startObject("fields")
                    .startObject("join_field")
                        .field("type", "join")
                        .startObject("relations")
                            .field("parent", "child")
                        .endObject()
                    .endObject()
                .endObject()
            .endObject()
            .endObject().endObject());
        IndexService indexService = createIndex("test");
        MapperParsingException exc = expectThrows(MapperParsingException.class,
            () -> indexService.mapperService().merge("type", new CompressedXContent(mapping),
                MapperService.MergeReason.MAPPING_UPDATE));
        assertThat(exc.getRootCause().getMessage(),
            containsString("join field [number.join_field] cannot be added inside an object or in a multi-field"));
    }

    public void testMultipleJoinFields() throws Exception {
        IndexService indexService = createIndex("test");
        {
            String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
                .startObject("properties")
                    .startObject("join_field")
                        .field("type", "join")
                        .startObject("relations")
                            .field("parent", "child")
                            .field("child", "grand_child")
                        .endObject()
                    .endObject()
                    .startObject("another_join_field")
                        .field("type", "join")
                        .startObject("relations")
                            .field("product", "item")
                        .endObject()
                    .endObject()
                .endObject()
                .endObject());
            IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> indexService.mapperService().merge("type",
                new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE));
            assertThat(exc.getMessage(), containsString("Field [_parent_join] is defined twice in [type]"));
        }

        {
            String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
                .startObject("properties")
                    .startObject("join_field")
                        .field("type", "join")
                        .startObject("relations")
                            .field("parent", "child")
                            .field("child", "grand_child")
                        .endObject()
                    .endObject()
                .endObject()
                .endObject());
            indexService.mapperService().merge("type",
                new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
            String updateMapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
                .startObject("properties")
                    .startObject("another_join_field")
                        .field("type", "join")
                    .endObject()
                .endObject()
                .endObject());
            IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> indexService.mapperService().merge("type",
                new CompressedXContent(updateMapping), MapperService.MergeReason.MAPPING_UPDATE));
            assertThat(exc.getMessage(), containsString("Field [_parent_join] is defined twice in [type]"));
        }
    }

    public void testEagerGlobalOrdinals() throws Exception {
        String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
            .startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .startObject("relations")
                        .field("parent", "child")
                        .field("child", "grand_child")
                    .endObject()
                .endObject()
            .endObject()
            .endObject());
        IndexService service = createIndex("test");
        DocumentMapper docMapper = service.mapperService().merge("type", new CompressedXContent(mapping),
            MapperService.MergeReason.MAPPING_UPDATE);
        assertTrue(docMapper.mappers().getMapper("join_field") == ParentJoinFieldMapper.getMapper(service.mapperService()));
        assertFalse(service.mapperService().fullName("join_field").eagerGlobalOrdinals());
        assertNotNull(service.mapperService().fullName("join_field#parent"));
        assertTrue(service.mapperService().fullName("join_field#parent").eagerGlobalOrdinals());
        assertNotNull(service.mapperService().fullName("join_field#child"));
        assertTrue(service.mapperService().fullName("join_field#child").eagerGlobalOrdinals());

        mapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
            .startObject("properties")
                .startObject("join_field")
                    .field("type", "join")
                    .field("eager_global_ordinals", false)
                    .startObject("relations")
                        .field("parent", "child")
                        .field("child", "grand_child")
                    .endObject()
                .endObject()
            .endObject()
            .endObject());
        service.mapperService().merge("type", new CompressedXContent(mapping),
            MapperService.MergeReason.MAPPING_UPDATE);
        assertFalse(service.mapperService().fullName("join_field").eagerGlobalOrdinals());
        assertNotNull(service.mapperService().fullName("join_field#parent"));
        assertFalse(service.mapperService().fullName("join_field#parent").eagerGlobalOrdinals());
        assertNotNull(service.mapperService().fullName("join_field#child"));
        assertFalse(service.mapperService().fullName("join_field#child").eagerGlobalOrdinals());
    }
}


text:
using System.Collections.Generic;

namespace ExistsForAll.Shepherd.SimpleInjector.UnitTests.Subjects
{
	public class SingleTypeCollectionHolder : ISingleTypeCollectionHolder
	{
		public IEnumerable<ISingleTypeCollection> Collection { get; }

		public SingleTypeCollectionHolder(IEnumerable<ISingleTypeCollection> singleTypeCollections)
		{
			Collection = singleTypeCollections;
		}
	}
}


text:
<resources>

    <!--
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    </style>
    -->

    <style name="AppTheme" parent="AppTheme.Base">
        <!-- Base application theme. Defining this lets values-v21/styles.xml reuse it with changes. -->
    </style>

    <style name="AppTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Use the Toolbar instead of the ActionBar (new in API 21 and AppCompat). -->
        <item name="windowActionBar">false</item>

        <item name="android:textColorPrimary">@color/white</item>

        <!-- colorPrimary is used, for instance, for the default ActionBar
               (but not Toolbar) background.
                We specify the same color for the toolbar background in
                toolbar.xml.. -->
        <item name="colorPrimary">@color/action_bar</item>

        <!-- colorPrimaryDark is used for the status bar (with the
             battery, clock, etc). -->
        <item name="colorPrimaryDark">@color/action_bar</item>

        <!-- colorAccent is used as the default value for
             colorControlActivated which is used to tint widgets. -->
        <item name="colorAccent">@color/action_bar</item>

        <!-- Color of action menu valueUpdateEvents in the action-bar -->
        <item name="actionMenuTextColor">@color/white</item>
        <item name="android:actionMenuTextColor">@color/white</item>
    </style>

</resources>