text:
package akka.rtcweb.protocol.ice.stun

import java.net.{ Inet4Address, InetAddress, InetSocketAddress }

import akka.rtcweb.protocol.scodec.SCodecContrib
import akka.rtcweb.protocol.scodec.SCodecContrib._
import scodec._
import scodec.bits.{ BitVector, ByteOrdering, ByteVector, HexStringSyntax }
import scodec.codecs._
import shapeless._

sealed trait StunAttributeType

/**
 * Known attribute types from [[https://tools.ietf.org/html/rfc5389#section-18.2]]
 */
object StunAttributeType {
  implicit val codec: Codec[StunAttributeType] = choice({
    mappedEnum(codecs.bits(16),
      `MAPPED-ADDRESS` -> hex"0x0001".bits,
      USERNAME -> hex"0x0006".bits,
      `MESSAGE-INTEGRITY` -> hex"0x0008".bits,
      `ERROR-CODE` -> hex"0x0009".bits,
      `UNKNOWN-ATTRIBUTES` -> hex"0x000A".bits,
      REALM -> hex"0x0014".bits,
      NONCE -> hex"0x0015".bits,
      `XOR-MAPPED-ADDRESS` -> hex"0x0020".bits,
      `ALTERNATE-SERVER` -> hex"0x8023".bits,
      PRIORITY -> hex"0x0024".bits,
      `USE-CANDIDATE` -> hex"0x0025".bits,
      SOFTWARE -> hex"0x8022".bits,
      FINGERPRINT -> hex"0x8028".bits,
      `ICE-CONTROLLED` -> hex"0x8029".bits,
      `ICE-CONTROLLING` -> hex"0x802A".bits
    )
  }, codecs.bits(16).as[UNKNOWN].upcast[StunAttributeType])

  final case class UNKNOWN(code: BitVector) extends StunAttributeType {
    /**
     * Tells whether a stun implementation is required to understand this StunAttribute
     * @see [[https://tools.ietf.org/html/rfc5389#section-15]]
     */
    def mustUnderstand: Boolean = code.toLong(signed = false, ByteOrdering.LittleEndian) <= hex"0x8000".toLong(signed = false, ByteOrdering.LittleEndian)
  }

  case object `MAPPED-ADDRESS` extends StunAttributeType
  case object USERNAME extends StunAttributeType
  case object `MESSAGE-INTEGRITY` extends StunAttributeType
  case object `ERROR-CODE` extends StunAttributeType
  case object `UNKNOWN-ATTRIBUTES` extends StunAttributeType
  case object REALM extends StunAttributeType
  case object NONCE extends StunAttributeType
  case object `XOR-MAPPED-ADDRESS` extends StunAttributeType
  case object SOFTWARE extends StunAttributeType
  case object `ALTERNATE-SERVER` extends StunAttributeType
  case object PRIORITY extends StunAttributeType
  case object `USE-CANDIDATE` extends StunAttributeType
  case object FINGERPRINT extends StunAttributeType
  case object `ICE-CONTROLLED` extends StunAttributeType
  case object `ICE-CONTROLLING` extends StunAttributeType

}

sealed trait Family

object Family {

  def fromAddress(inetAddress: InetAddress) = inetAddress match {
    case _: Inet4Address => Family.IPv4
    case _: InetAddress => Family.IPv6
  }

  implicit val codec: Codec[Family] = mappedEnum(uint8, IPv4 -> 1, IPv6 -> 2)

  case object IPv4 extends Family

  case object IPv6 extends Family
}

final case class SOFTWARE(description: String) extends StunAttribute(StunAttributeType.SOFTWARE) {
  require(description.length < 128, "description must be less than 128 characters")
}

object SOFTWARE {

  implicit val codec: Codec[SOFTWARE] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.SOFTWARE), boundedSizeBytes(763, utf8)).as[SOFTWARE]

  implicit val discriminator: Discriminator[StunAttribute, SOFTWARE, StunAttributeType] = Discriminator(StunAttributeType.SOFTWARE)
}

final case class `UNKNOWN-ATTRIBUTES`(unknownAttributeTypes: Vector[StunAttributeType]) extends StunAttribute(StunAttributeType.`UNKNOWN-ATTRIBUTES`)

object `UNKNOWN-ATTRIBUTES` {
  /**
   * 0                   1                   2                   3
   * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |      Attribute 1 Type           |     Attribute 2 Type        |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |      Attribute 3 Type           |     Attribute 4 Type    ...
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   */
  implicit val codec: Codec[`UNKNOWN-ATTRIBUTES`] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`UNKNOWN-ATTRIBUTES`),
      vector(StunAttributeType.codec)
    ).as[`UNKNOWN-ATTRIBUTES`]
  implicit val discriminator: Discriminator[StunAttribute, `UNKNOWN-ATTRIBUTES`, StunAttributeType] = Discriminator(StunAttributeType.`UNKNOWN-ATTRIBUTES`)
}

/**
 * The ERROR-CODE attribute is used in error response messages.  It
 * contains a numeric error code value in the range of 300 to 699 plus a
 * textual reason phrase encoded in UTF-8 [RFC3629], and is consistent
 * in its code assignments and semantics with SIP [RFC3261] and HTTP
 * [RFC2616].  The reason phrase is meant for user consumption, and can
 * be anything appropriate for the error code.  Recommended reason
 * phrases for the defined error codes are included in the IANA registry
 * for error codes.  The reason phrase MUST be a UTF-8 [RFC3629] encoded
 * sequence of less than 128 characters (which can be as long as 763
 * bytes).
 *
 * @see [[https://tools.ietf.org/html/rfc5389#section-15.6]]
 */
final case class `ERROR-CODE`(errorCode: `ERROR-CODE`.Code, reasonPhrase: String) extends StunAttribute(StunAttributeType.`ERROR-CODE`) {

}

object `ERROR-CODE` {

  sealed trait Code
  object Code {

    implicit val codec: Codec[`ERROR-CODE`.Code] = choice(mappedEnum(classNumberCodec,
      `Try Alternate` -> 300,
      `Bad Request` -> 400,
      Unauthorized -> 401,
      `Unknown Attribute` -> 420,
      `Stale Nonce` -> 438,
      `Role Conflict` -> 487,
      `Server Error` -> 500
    ), classNumberCodec.as[Code.UNKNOWN].upcast[`ERROR-CODE`.Code])

    /** Failure case: ERROR-CODE is now known */
    final case class UNKNOWN(number: Int) extends Code

    /**
     * Try Alternate: The client should contact an alternate server for
     * this request.  This error response MUST only be sent if the
     * request included a USERNAME attribute and a valid MESSAGE-
     * INTEGRITY attribute; otherwise, it MUST NOT be sent and error
     * code 400 (Bad Request) is suggested.  This error response MUST
     * be protected with the [[`MESSAGE-INTEGRITY`]] attribute, and receivers
     * MUST validate the [[`MESSAGE-INTEGRITY`]] of this response before
     * redirecting themselves to an alternate server.
     */
    case object `Try Alternate` extends Code

    /**
     * Bad Request: The request was malformed.  The client SHOULD NOT
     * retry the request without modification from the previous
     * attempt.  The server may not be able to generate a valid
     * MESSAGE-INTEGRITY for this error, so the client MUST NOT expect
     * a valid MESSAGE-INTEGRITY attribute on this response.
     */
    case object `Bad Request` extends Code

    /**
     * Unauthorized: The request did not contain the correct
     * credentials to proceed.  The client should retry the request
     * with proper credentials.
     */
    case object Unauthorized extends Code

    /**
     * Unknown Attribute: The server received a STUN packet containing
     * a comprehension-required attribute that it did not understand.
     * The server MUST put this unknown attribute in the UNKNOWN-
     * ATTRIBUTE attribute of its error response.
     */
    case object `Unknown Attribute` extends Code

    /**
     * The NONCE used by the client was no longer valid.
     * The client should retry, using the NONCE provided in the
     * response.
     */
    case object `Stale Nonce` extends Code
    /**
     * Server Error: The server has suffered a temporary error.  The
     * client should try again.
     */
    case object `Server Error` extends Code

    /**
     * The Binding request contained either the ICE-
     * CONTROLLING or ICE-CONTROLLED attribute, indicating a role that
     * conflicted with the server.  The server ran a tie-breaker based on
     * the tie-breaker value in the request and determined that the
     * client needs to switch roles.
     * @see [[https://tools.ietf.org/html/rfc5245#section-19.2]]
     */
    case object `Role Conflict` extends Code
  }

  /**
   * The Class represents
   * the hundreds digit of the error code.  The value MUST be between 3
   * and 6.  The Number represents the error code modulo 100, and its
   * value MUST be between 0 and 99.
   */
  private val classNumberCodec: Codec[Int] = {
    {
      "Class" | uint(3)
    } :: {
      "Number" | uint8
    }
  }.xmap[Int]({ case clazz :: number :: HNil => clazz * 100 + number }, { code => code / 100 :: code % 100 :: HNil })

  /**
   * {{{
   * 0                   1                   2                   3
   * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |           Reserved, should be 0         |Class|     Number    |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |      Reason Phrase (variable)                                ..
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * }}}
   */
  implicit val codec = {
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`ERROR-CODE`),
      ignore(21) ::
        Code.codec :: {
          "ReasonPhrase" | boundedSizeBytes(763, utf8)
        })
  }.as[`ERROR-CODE`]
  implicit val discriminator: Discriminator[StunAttribute, `ERROR-CODE`, StunAttributeType] = Discriminator(StunAttributeType.`ERROR-CODE`)

}

/**
 * The USERNAME attribute is used for message integrity.  It identifies
 * the username and password combination used in the message-integrity
 * check.
 *
 * The value of USERNAME is a variable-length value.  It MUST contain a
 * UTF-8 [RFC3629] encoded sequence of less than 513 bytes, and MUST
 * have been processed using SASLprep [RFC4013].
 */
final case class USERNAME(username: String) extends StunAttribute(StunAttributeType.USERNAME)

object USERNAME {
  //TODO: SASLprep
  implicit val codec: Codec[USERNAME] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.USERNAME),
      boundedSizeBytes(513, utf8).as[USERNAME])
  implicit val discriminator: Discriminator[StunAttribute, USERNAME, StunAttributeType] = Discriminator(StunAttributeType.USERNAME)
}

/**
 * The REALM attribute may be present in requests and responses.  It
 * contains text that meets the grammar for "realm-value" as described
 * in RFC 3261 [RFC3261] but without the double quotes and their
 * surrounding whitespace.  That is, it is an unquoted realm-value (and
 * is therefore a sequence of qdtext or quoted-pair).  It MUST be a
 * UTF-8 [RFC3629] encoded sequence of less than 128 characters (which
 * can be as long as 763 bytes), and MUST have been processed using
 * SASLprep [RFC4013].
 *
 * Presence of the REALM attribute in a request indicates that long-term
 * credentials are being used for authentication.  Presence in certain
 * error responses indicates that the server wishes the client to use a
 * long-term credential for authentication.
 * @see [[https://tools.ietf.org/html/rfc5389#section-15.7]]
 */
final case class REALM(realmValue: String) extends StunAttribute(StunAttributeType.REALM)

object REALM {
  //TODO: SASLprep
  implicit val codec: Codec[REALM] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.REALM),
      boundedSizeBytes(763, utf8).as[REALM])
  implicit val discriminator: Discriminator[StunAttribute, REALM, StunAttributeType] = Discriminator(StunAttributeType.REALM)
}

/**
 * The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of
 * the STUN message.  The MESSAGE-INTEGRITY attribute can be present in
 * any STUN message type.  Since it uses the SHA1 hash, the HMAC will be
 * 20 bytes.  The text used as input to HMAC is the STUN message,
 * including the header, up to and including the attribute preceding the
 * MESSAGE-INTEGRITY attribute.  With the exception of the FINGERPRINT
 * attribute, which appears after MESSAGE-INTEGRITY, agents MUST ignore
 * all other attributes that follow MESSAGE-INTEGRITY.
 *
 * The key for the HMAC depends on whether long-term or short-term
 * credentials are in use.  For long-term credentials, the key is 16
 * bytes:
 *
 *         {{{ key = MD5(username ":" realm ":" SASLprep(password)) }}}
 *
 * That is, the 16-byte key is formed by taking the MD5 hash of the
 * result of concatenating the following five fields: (1) the username,
 * with any quotes and trailing nulls removed, as taken from the
 * USERNAME attribute (in which case SASLprep has already been applied);
 * (2) a single colon; (3) the realm, with any quotes and trailing nulls
 * removed; (4) a single colon; and (5) the password, with any trailing
 * nulls removed and after processing using SASLprep.  For example, if
 * the username was 'user', the realm was 'realm', and the password was
 * 'pass', then the 16-byte HMAC key would be the result of performing
 * an MD5 hash on the string 'user:realm:pass', the resulting hash being
 * 0x8493fbc53ba582fb4c044c456bdc40eb.
 *
 * For short-term credentials:
 *
 * {{{                     key = SASLprep(password)}}}
 *  @see [[https://tools.ietf.org/html/rfc5389#section-15.4]]
 */
final case class `MESSAGE-INTEGRITY`(sha1: ByteVector) extends StunAttribute(StunAttributeType.`MESSAGE-INTEGRITY`)

object `MESSAGE-INTEGRITY` {
  //TODO: SASLprep
  implicit val codec: Codec[`MESSAGE-INTEGRITY`] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`MESSAGE-INTEGRITY`),
      bytes(20).as[`MESSAGE-INTEGRITY`])

  implicit val discriminator: Discriminator[StunAttribute, `MESSAGE-INTEGRITY`, StunAttributeType] = Discriminator(StunAttributeType.`MESSAGE-INTEGRITY`)
}

/**
 * The alternate server represents an alternate transport address
 * identifying a different STUN server that the STUN client should try.
 *
 * It is encoded in the same way as [[`MAPPED-ADDRESS`]], and thus refers to a
 * single server by IP address.  The IP address family MUST be identical
 * to that of the source IP address of the request.
 * @see [[https://tools.ietf.org/html/rfc5389#section-15.11]]
 */
final case class `ALTERNATE-SERVER`(family: Family, port: Int, address: InetAddress) extends StunAttribute(StunAttributeType.`ALTERNATE-SERVER`) {
  lazy val inetSocketAddress = new InetSocketAddress(address, port)
}

object `ALTERNATE-SERVER` {
  implicit val codec: Codec[`ALTERNATE-SERVER`] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`ALTERNATE-SERVER`),
      StunAttribute.addressCodec).as[`ALTERNATE-SERVER`]
  implicit val discriminator: Discriminator[StunAttribute, `ALTERNATE-SERVER`, StunAttributeType] = Discriminator(StunAttributeType.`ALTERNATE-SERVER`)
}

/**
 * The MAPPED-ADDRESS attribute indicates a reflexive transport address
 * of the client.  It consists of an 8-bit address family and a 16-bit
 * port, followed by a fixed-length value representing the IP address.
 * If the address family is IPv4, the address MUST be 32 bits.  If the
 * address family is IPv6, the address MUST be 128 bits.  All fields
 * must be in network byte order.
 * @see [[https://tools.ietf.org/html/rfc5389#section-15.1]]
 */
final case class `MAPPED-ADDRESS`(family: Family, port: Int, address: InetAddress) extends StunAttribute(StunAttributeType.`MAPPED-ADDRESS`) {
  lazy val inetSocketAddress = new InetSocketAddress(address, port)
}

object `MAPPED-ADDRESS` {
  implicit val codec: Codec[`MAPPED-ADDRESS`] =
    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`MAPPED-ADDRESS`),
      StunAttribute.addressCodec).as[`MAPPED-ADDRESS`]

  implicit val discriminator: Discriminator[StunAttribute, `MAPPED-ADDRESS`, StunAttributeType] = Discriminator(StunAttributeType.`MAPPED-ADDRESS`)
}

final case class `XOR-MAPPED-ADDRESS`(family: Family, port: Int, address: InetAddress) extends StunAttribute(StunAttributeType.`XOR-MAPPED-ADDRESS`) {
  lazy val inetSocketAddress = new InetSocketAddress(address, port)
}

object `XOR-MAPPED-ADDRESS` {

  /**
   * {{{
   * 0                   1                   2                   3
   * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |x x x x x x x x|    Family     |         X-Port                |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                X-Address (Variable)
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * }}}
   */
  implicit val codec: Codec[`XOR-MAPPED-ADDRESS`] = {

    StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`XOR-MAPPED-ADDRESS`),
      ignore(8) :: {
        "Family" | Family.codec >>:~ { family =>
          {
            "X-Port" | xPortCodec
          } :: {
            "X-Address" | {
              family match {
                case Family.IPv4 => SCodecContrib.xor(ipv4Address, StunMessage.MAGIC_COOKIE)
                case Family.IPv6 => ??? // cannot be done yet since we do not have the transaction id here //ipv6Address
              }
            }
          }
        }
      }
    )

  }.as[`XOR-MAPPED-ADDRESS`]

  implicit val discriminator: Discriminator[StunAttribute, `XOR-MAPPED-ADDRESS`, StunAttributeType] = Discriminator(StunAttributeType.`XOR-MAPPED-ADDRESS`)
  private final val MAGIC_COOKIE_MSBS = StunMessage.MAGIC_COOKIE.take(16)

  final def xPortCodec: Codec[Int] = new Codec[Int] {
    override def encode(b: Int): Attempt[BitVector] = uint16.encode(b).map(_.xor(StunMessage.MAGIC_COOKIE))

    override def decode(buffer: BitVector): Attempt[DecodeResult[Int]] = {
      val (xPortRaw, rest) = buffer.splitAt(16)
      uint16.decode(xPortRaw.xor(MAGIC_COOKIE_MSBS)).map { case DecodeResult(a, _) => DecodeResult[Int](a, rest) }
    }

    override def sizeBound: SizeBound = SizeBound.exact(16)
  }

}

/** @see [[https://tools.ietf.org/html/rfc5389#section-15.5]]*/
final case class FINGERPRINT(crc32: Long) extends StunAttribute(StunAttributeType.FINGERPRINT)

object FINGERPRINT {

  val dummy = FINGERPRINT(0L)
  implicit val codec: Codec[FINGERPRINT] = StunAttribute.withAttributeHeader(constantValue(StunAttributeType.FINGERPRINT),
    uint32
  ).hlist.as[FINGERPRINT]
  implicit val discriminator: Discriminator[StunAttribute, FINGERPRINT, StunAttributeType] = Discriminator(StunAttributeType.FINGERPRINT)
}

/** @see [[https://tools.ietf.org/html/rfc5245#section-19.1]]*/
final case class `USE-CANDIDATE`() extends StunAttribute(StunAttributeType.`USE-CANDIDATE`)

object `USE-CANDIDATE` {
  implicit val codec: Codec[`USE-CANDIDATE`] = StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`USE-CANDIDATE`),
    ignore(0)
  ).hlist.as[`USE-CANDIDATE`]
  implicit val discriminator: Discriminator[StunAttribute, `USE-CANDIDATE`, StunAttributeType] = Discriminator(StunAttributeType.`USE-CANDIDATE`)
}

/** @see [[https://tools.ietf.org/html/rfc5245#section-19.1]]*/
final case class PRIORITY(byteVector: Long) extends StunAttribute(StunAttributeType.PRIORITY)

object PRIORITY {
  implicit val codec: Codec[PRIORITY] = StunAttribute.withAttributeHeader(constantValue(StunAttributeType.PRIORITY),
    uint32
  ).hlist.as[PRIORITY]
  implicit val discriminator: Discriminator[StunAttribute, PRIORITY, StunAttributeType] = Discriminator(StunAttributeType.PRIORITY)
}

/** @see [[https://tools.ietf.org/html/rfc5245#section-19.1]]*/
final case class `ICE-CONTROLLED`(byteVector: ByteVector) extends StunAttribute(StunAttributeType.`ICE-CONTROLLED`)

object `ICE-CONTROLLED` {
  implicit val codec: Codec[`ICE-CONTROLLED`] = StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`ICE-CONTROLLED`),
    bytes(8)
  ).hlist.as[`ICE-CONTROLLED`]
  implicit val discriminator: Discriminator[StunAttribute, `USE-CANDIDATE`, StunAttributeType] = Discriminator(StunAttributeType.`USE-CANDIDATE`)
}

/** @see [[https://tools.ietf.org/html/rfc5245#section-19.1]]*/
final case class `ICE-CONTROLLING`(byteVector: ByteVector) extends StunAttribute(StunAttributeType.`ICE-CONTROLLING`)

object `ICE-CONTROLLING` {
  implicit val codec: Codec[`ICE-CONTROLLING`] = StunAttribute.withAttributeHeader(constantValue(StunAttributeType.`ICE-CONTROLLING`),
    bytes(8)
  ).hlist.as[`ICE-CONTROLLING`]
  implicit val discriminator: Discriminator[StunAttribute, `USE-CANDIDATE`, StunAttributeType] = Discriminator(StunAttributeType.`ICE-CONTROLLING`)
}

/**
 * @see [[https://tools.ietf.org/html/rfc5389#section-15]]
 */
sealed abstract class StunAttribute(val attributeType: StunAttributeType)

object StunAttribute {

  /**
   * {{{
   *  0                   1                   2                   3
   *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |         Type                  |            Length             |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                         Value (variable)                ....
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * }}}
   *
   * The value in the length field MUST contain the length of the Value
   * part of the attribute, prior to padding, measured in bytes.  Since
   * STUN aligns attributes on 32-bit boundaries, attributes whose content
   * is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of
   * padding so that its value contains a multiple of 4 bytes.  The
   * padding bits are ignored, and may be any value.
   *
   * Any attribute type MAY appear more than once in a STUN message.
   * Unless specified otherwise, the order of appearance is significant:
   * only the first occurrence needs to be processed by a receiver, and
   * any duplicates MAY be ignored by a receiver.
   *
   * To allow future revisions of this specification to add new attributes
   * if needed, the attribute space is divided into two ranges.
   * Attributes with type values between 0x0000 and 0x7FFF are
   * comprehension-required attributes, which means that the STUN agent
   * cannot successfully process the message unless it understands the
   * attribute.  Attributes with type values between 0x8000 and 0xFFFF are
   * comprehension-optional attributes, which means that those attributes
   * can be ignored by the STUN agent if it does not understand them.
   *
   * The set of STUN attribute types is maintained by IANA.  The initial
   * set defined by this specification is found in Section 18.2.
   *
   * The rest of this section describes the format of the various
   * attributes defined in this specification.
   */
  implicit lazy val codec: Codec[StunAttribute] = Codec.coproduct[StunAttribute].choice.as[StunAttribute]
  implicit val discriminated: Discriminated[StunAttribute, StunAttributeType] = Discriminated(StunAttributeType.codec)

  /** Helper for concrete [[StunAttribute]]s **/
  def withAttributeHeader[A, D](discriminator: Codec[Unit], valueCodec: Codec[A]): Codec[A] = {
    blockalignBytes(
      discriminator ~>
        variableSizeBytes[A]({
          "Length" | uint16
        },
          valueCodec
        ), 4)
  }

  /**
   * {{{
   * 0                   1                   2                   3
   * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |0 0 0 0 0 0 0 0|    Family     |           Port                |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * |                                                               |
   * |                 Address (32 bits or 128 bits)                 |
   * |                                                               |
   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   * }}}
   */
  def addressCodec: Codec[Family :: Int :: InetAddress :: HNil] = {
    ignore(8) :: {
      "Family" | Family.codec >>:~ { family =>
        {
          "Port" | uint8
        } :: {
          "Address" | {
            family match {
              case Family.IPv4 => ipv4Address
              case Family.IPv6 => ipv6Address
            }
          }
        }
      }
    }
  }.dropUnits

}


text:
Leaflet Markers with a custom DOM element icon.

Leaflet.DomMarkers.Icon extends the Leaflet.DivIcon object so the same config properties can be used (except the `html` one which is replaced by `element`

The initial idea was to be used inside the [angular-leaflet-directive](https://github.com/tombatossals/angular-leaflet-directive/) and to display interactive icons on the map. The DOM element is generated by the *angular-leaflet-directive* and provided to the Leaflet.DomMarkers.Icon through the `element` property:

```js
var domElement = yourDomElementCreationFunction();
var icon = L.DomMarkers.icon({
  element: domElement,
  iconSize: [20, 20],
  //... other Icon/DivIcon properties
});
```

redpajama_set_name: RedPajamaGithub


text:
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

### 2.0.0

- Added support for React async mode
- Added `useDebouncedInput` hook to simplify usage

### 1.0.0

- First release 🌈


text:
"""
Utilities to manage different data input files.
"""
import logging
from collections import namedtuple
from xml.etree.ElementTree import ElementTree

from tqdm import tqdm
from .schema import MentionInstance

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

class Provenance(namedtuple("Provenance", ["doc_id", "start", "end"])):
    @classmethod
    def from_str(cls, str_):
        doc_id, start_end = str_.split(':', 1)
        start, end = map(int, start_end.split('-', 1))
        return cls(doc_id, start, end)

    def __str__(self):
        return "{}:{}-{}".format(self.doc_id, self.start, self.end)

def test_provenance_from_str():
    str_ = "ENG_NW_001278_20130214_F00011JDX:1448-1584"
    p = Provenance.from_str(str_)
    assert p.doc_id == "ENG_NW_001278_20130214_F00011JDX"
    assert p.start == 1448
    assert p.end == 1584

def test_provenance_cmp():
    p1 = Provenance("A", 10, 20)
    p2 = Provenance("A", 10, 20)
    p3 = Provenance("A", 15, 24)
    p4 = Provenance("B", 10, 20)

    assert p1 == p2
    assert p1 <= p2
    assert p1 < p3
    assert p3 > p1
    assert p1 < p4

class EvaluationEntry(namedtuple("EvaluationEntry", ["id", "query_id", 'ldc_id', "relation", "relation_provenances", "slot_value", "slot_provenances", "slot_value_label", "relation_label", "eq_class", "eq"])):
    def __str__(self):
        return "{}: {} {} {}".format(self.id, self.query_id, self.relation, self.slot_value)

    def __repr__(self):
        return "<Entry: {}>".format(str(self))

    def is_true(self):
        return self.eq > 0

    @classmethod
    def from_line(cls, line):
        parts = line.split("\t")
        id_ = parts[0]
        query_id, relation = parts[1].split(':', 1)
        ldc_id = None
        relation_provenances = [Provenance.from_str(s) for s in parts[2].split(',')]
        slot_value = parts[3]
        slot_provenances = [Provenance.from_str(s) for s in parts[4].split(',')]
        slot_value_label = parts[5]
        relation_label = parts[6]
        eq_class = parts[7]
        eq = int(parts[7].split(":")[-1])
        return cls(id_, query_id, ldc_id, relation, relation_provenances, slot_value, slot_provenances, slot_value_label, relation_label, eq_class, eq)

    def to_list(self):
        return [
            self.query_id,
            self.relation,
            self.slot_value,
            self.slot_value_label,
            self.relation_label,
            self.eq_class,]

def test_evaluation_entry():
    line = "CS15_ENG_0016_0_001	CS15_ENG_0016:gpe:births_in_country	ENG_NW_001278_20130214_F00011JDX:1448-1584	Agriculture	ENG_NW_001278_20130214_F00011JDX:1505-1515	W	W	0"
    entry = EvaluationEntry.from_line(line)
    assert entry.id == "CS15_ENG_0016_0_001"
    assert entry.query_id == "CS15_ENG_0016"
    assert entry.relation == "gpe:births_in_country"
    assert entry.relation_provenances == [Provenance("ENG_NW_001278_20130214_F00011JDX", 1448, 1584)]
    assert entry.slot_value == "Agriculture"
    assert entry.slot_provenances == [Provenance("ENG_NW_001278_20130214_F00011JDX", 1505, 1515)]
    assert entry.slot_value_label == "W"
    assert entry.relation_label == "W"
    assert entry.eq_class == "0"

class OutputEntry(namedtuple("EvaluationEntry", ["query_id", "ldc_id", "relation", "run_id", "relation_provenances", "slot_value", "slot_type", "slot_provenances", "confidence"])):
    @classmethod
    def from_line(cls, line):
        parts = line.split("\t")
        query_id = parts[0]
        ldc_id = None
        relation = parts[1]
        run_id = parts[2]
        relation_provenances = [Provenance.from_str(s) for s in parts[3].split(',')]
        slot_value = parts[4]
        slot_type = parts[5]
        slot_provenances = [Provenance.from_str(s) for s in parts[6].split(',')]
        confidence = float(parts[7])
        return cls(query_id, ldc_id, relation, run_id, relation_provenances, slot_value, slot_type, slot_provenances, confidence)

def test_output_entry():
    line = "CSSF15_ENG_001e2aa16f	gpe:births_in_city	KB_BBN1	NYT_ENG_20130513.0090:2476-2540	Kenneth Everette Battelle	PER	NYT_ENG_20130513.0090:2476-2500	0.9"
    entry = OutputEntry.from_line(line)
    assert entry.query_id == "CSSF15_ENG_001e2aa16f"
    assert entry.relation == "gpe:births_in_city"
    assert entry.run_id == "KB_BBN1"
    assert entry.relation_provenances == [Provenance("NYT_ENG_20130513.0090",2476,2540)]
    assert entry.slot_value == "Kenneth Everette Battelle"
    assert entry.slot_type == "PER"
    assert entry.slot_provenances == [Provenance("NYT_ENG_20130513.0090", 2476,2500)]
    assert entry.confidence == 0.9

def load_queries(fstream):
    Q = {}
    for line in fstream:
        fields = line.split()
        # NOTE: We are considering partial assessments because that's
        # what KBP is doing too.
        ldc_query, cssf_query = fields[:2]
        Q[cssf_query] = ldc_query
    return Q

def load_gold(fstream, Q):
    gold = []
    for line in tqdm(fstream):
        entry = EvaluationEntry.from_line(line)
        if entry.query_id in Q:
            gold.append(entry._replace(ldc_id=Q[entry.query_id]))
    logger.info("Loaded %d evaluation entries", len(gold))
    return gold

def load_gold_2016(fstream, Q):
    gold = []
    for line in tqdm(fstream):
        parts = line.split("\t")
        line = "\t".join(parts[0:6] + parts[7:9])
        entry = EvaluationEntry.from_line(line)
        if entry.query_id in Q:
            gold.append(entry._replace(ldc_id=Q[entry.query_id]))
    logger.info("Loaded %d evaluation entries", len(gold))
    return gold

def load_output(fstream, Q):
    output = []
    for line in tqdm(fstream, desc='Loading entries'):
        entry = OutputEntry.from_line(line)
        if entry.query_id in Q:
            output.append(entry._replace(ldc_id=Q[entry.query_id]))
    #logger.info("Loaded %d output entries.", len(output))
    return output

QueryEntry = namedtuple("QueryEntry", ["id", "gloss", "mention_type", "prov", "slot"])
def load_query_entries(f):
    tree = ElementTree()
    tree.parse(f)

    E = []
    for query in tree.getroot().getchildren():
        query_id = query.get('id')
        gloss = query.find("name").text
        mention_type = query.find("enttype").text.upper()
        docid = query.find("docid").text
        beg, end = int(query.find("beg").text), int(query.find("end").text)+1
        prov = Provenance(docid, beg, end)
        slot = query.find("slot0").text
        E.append(QueryEntry(query_id, gloss, mention_type, prov, slot))

    return E


text:
package liberty_paintball.endpoints;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static liberty_paintball.Config.APPLICATION_NAME;
import static liberty_paintball.Config.ENDPOINT_PATH_LEAVE;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

import liberty_paintball.game.Game;
import liberty_paintball.json.requests.LeaveGameRequest;

/**
 * @author Dave Waddling
 *
 * LeaveEndpoint consumes a LeaveGameRequest object and returns nothing.
 *
 */
@ApplicationPath(APPLICATION_NAME)
@Path(ENDPOINT_PATH_LEAVE)
public class LeaveEndpoint {

	@POST
	@Consumes(APPLICATION_JSON)
	public void leave(LeaveGameRequest request) {
		Game.getInstance().handleLeaveGameRequest(request);
		Response.ok().build();
	}

}


text:
//show the order-details with ajax
function showOrder(mode, var_content, file)
{
	$.get(
		file,
		((mode === 1) ? {'id_order': var_content, 'ajax': true} : {'id_order_return': var_content, 'ajax': true}),
		function(data)
		{
			$('#block-order-detail').fadeOut('slow', function()
			{
				$(this).html(data);
				$('.footab').footable();
				/* if return is allowed*/
				if ($('#order-detail-content .order_cb').length > 0)
				{
					//return slip : check or uncheck every checkboxes
					$('#order-detail-content th input[type=checkbox]').click(function()
					{
							$('#order-detail-content td input[type=checkbox]').each(function()
							{
								this.checked = $('#order-detail-content th input[type=checkbox]').is(':checked');
								updateOrderLineDisplay(this);
							});
					});
					//return slip : enable or disable 'global' quantity editing
					$('#order-detail-content td input[type=checkbox]').click(function()
					{
						updateOrderLineDisplay(this);
					});
					//return slip : limit quantities
					$('#order-detail-content td .order_qte_input').keyup(function()
					{
						var maxQuantity = parseInt($(this).parent().find('.order_qte_span').text());
						var quantity = parseInt($(this).val());
						if (isNaN($(this).val()) && $(this).val() !== '')
						{
							$(this).val(maxQuantity);
						}
						else
						{
							if (quantity > maxQuantity)
								$(this).val(maxQuantity);
							else if (quantity < 1)
								$(this).val(1);
						}
					});
					// The button to increment the product return value
					$(document).on('click', '.return_quantity_down', function(e){
						e.preventDefault();
						var $input = $(this).parent().parent().find('input');
						var count = parseInt($input.val()) - 1;
						count = count < 1 ? 1 : count;
						$input.val(count);
						$input.change();
					});
					// The button to decrement the product return value
					$(document).on('click', '.return_quantity_up', function(e){
						e.preventDefault();
						var maxQuantity = parseInt($(this).parent().parent().find('.order_qte_span').text());
						var $input = $(this).parent().parent().find('input');
						var count = parseInt($input.val()) + 1;
						count = count > maxQuantity ? maxQuantity : count;
						$input.val(count);
						$input.change();
					});
				}
				//catch the submit event of sendOrderMessage form
				$('form#sendOrderMessage').submit(function(){
					return sendOrderMessage();
			});
			$(this).fadeIn('slow', function() {
				$.scrollTo(this, 1200);
			});
		});
	});
}

function updateOrderLineDisplay(domCheckbox)
{
	var lineQuantitySpan = $(domCheckbox).parent().parent().find('.order_qte_span');
	var lineQuantityInput = $(domCheckbox).parent().parent().find('.order_qte_input');
	var lineQuantityButtons = $(domCheckbox).parent().parent().find('.return_quantity_up, .return_quantity_down');
	if($(domCheckbox).is(':checked'))
	{
		lineQuantitySpan.hide();
		lineQuantityInput.show();
		lineQuantityButtons.show();
	}
	else
	{
		lineQuantityInput.hide();
		lineQuantityButtons.hide();
		lineQuantityInput.val(lineQuantitySpan.text());
		lineQuantitySpan.show();
	}
}

//send a message in relation to the order with ajax
function sendOrderMessage()
{
	paramString = "ajax=true";
	$('#sendOrderMessage').find('input, textarea, select').each(function(){
		paramString += '&' + $(this).attr('name') + '=' + encodeURIComponent($(this).val());
	});

	$.ajax({
		type: "POST",
		headers: { "cache-control": "no-cache" },
		url: $('#sendOrderMessage').attr("action") + '?rand=' + new Date().getTime(),
		data: paramString,
		beforeSend: function(){
			$(".button[name=submitMessage]").prop("disabled", "disabled");
		},
		success: function(msg){
			$('#block-order-detail').fadeOut('slow', function() {
				$(this).html(msg);
				//catch the submit event of sendOrderMessage form
				$('#sendOrderMessage').submit(function(){
					return sendOrderMessage();
				});
				$(this).fadeIn('slow');
	        	$(".button[name=submitMessage]").prop("disabled", false);
			});
		},
		error: function(){
			$(".button[name=submitMessage]").prop("disabled", false);
		}
	});
	return false;
}


text:
// Copyright 2009 the Sputnik authors.  All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/**
 * String.prototype.substring (start, end) can be applied to non String object instance and
 * returns a string value(not object)
 *
 * @path ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A3_T10.js
 * @description Checknig if applying String.prototype.substring to Function object instance passes
 */

__FACTORY.prototype.substring = String.prototype.substring;

var __instance = new __FACTORY(void 0);

//////////////////////////////////////////////////////////////////////////////
//CHECK#1
if (__instance.substring(0, 100) !== "undefined") {
  $ERROR('#1: __instance.substring(0, 100) === "undefined". Actual: '+__instance.substring(0, 100) );
}
//
//////////////////////////////////////////////////////////////////////////////

function __FACTORY( value ) {
    this.value = value;
    this.toString = function() { return this.value+''; }
}


text:
namespace bp = ::boost::process;
namespace but = ::boost::unit_test;

namespace boost {
namespace process {
namespace detail {

// Tests are declared in this class so that we can access stream_behavior's
// internals. This is the only way to check the constructors.
struct stream_info
{
    static void test_capture()
    {
        bp::stream_behavior sb = bp::capture_stream();
        BOOST_CHECK_EQUAL(sb.get_type(), bp::stream_behavior::capture);
    }

    static void test_close()
    {
        bp::stream_behavior sb = bp::close_stream();
        BOOST_CHECK_EQUAL(sb.get_type(), bp::stream_behavior::close);
    }

    static void test_inherit()
    {
        bp::stream_behavior sb = bp::inherit_stream();
        BOOST_CHECK_EQUAL(sb.get_type(), bp::stream_behavior::inherit);
    }

    static void test_redirect_to_stdout()
    {
        bp::stream_behavior sb = bp::redirect_stream_to_stdout();
        BOOST_CHECK_EQUAL(sb.get_type(),
                          bp::stream_behavior::redirect_to_stdout);
    }

    static void test_silence()
    {
        bp::stream_behavior sb = bp::silence_stream();
        BOOST_CHECK_EQUAL(sb.get_type(), bp::stream_behavior::silence);
    }

#if defined(BOOST_POSIX_API)
    static void test_posix_redirect()
    {
        bp::stream_behavior sb1 = bp::posix_redirect_stream(1);
        BOOST_CHECK_EQUAL(sb1.get_type(),
                          bp::stream_behavior::posix_redirect);
        BOOST_CHECK_EQUAL(sb1.desc_to_, 1);

        bp::stream_behavior sb2 = bp::posix_redirect_stream(2);
        BOOST_CHECK_EQUAL(sb2.get_type(),
                          bp::stream_behavior::posix_redirect);
        BOOST_CHECK_EQUAL(sb2.desc_to_, 2);
    }
#endif
};

}
}
}

but::test_suite *init_unit_test_suite(int argc, char *argv[])
{
    using boost::process::detail::stream_info;

    but::test_suite *test = BOOST_TEST_SUITE("stream_behavior test suite");

    test->add(BOOST_TEST_CASE(&stream_info::test_capture));
    test->add(BOOST_TEST_CASE(&stream_info::test_close));
    test->add(BOOST_TEST_CASE(&stream_info::test_inherit));
    test->add(BOOST_TEST_CASE(&stream_info::test_redirect_to_stdout));
    test->add(BOOST_TEST_CASE(&stream_info::test_silence));
#if defined(BOOST_POSIX_API)
    test->add(BOOST_TEST_CASE(&stream_info::test_posix_redirect));
#endif

    return test;
}


text:
package org.uiautomation.ios.command;

import org.json.JSONObject;
import org.openqa.selenium.remote.Response;
import org.uiautomation.ios.IOSServerManager;
import org.uiautomation.ios.servlet.WebDriverLikeRequest;

/**
 * Handler to navigate to a specified url.
 */
public class GetHandler extends CommandHandler {
  public GetHandler(IOSServerManager driver, WebDriverLikeRequest request) {
    super(driver, request);
  }

  @Override
  public Response handle() throws Exception {
    String url = getRequest().getPayload().getString("url");
    getWebDriver().get(url);
    Response res = new Response();
    res.setSessionId(getSession().getSessionId());
    res.setStatus(0);
    res.setValue(new JSONObject());
    return res;
  }
}


text:
package org.d2rq.db.expr;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.d2rq.db.op.DatabaseOp;
import org.d2rq.db.renamer.Renamer;
import org.d2rq.db.schema.ColumnName;
import org.d2rq.db.types.DataType;
import org.d2rq.db.types.DataType.GenericType;
import org.d2rq.db.vendor.Vendor;

/**
 * An {@link Expression} defined directly by a raw SQL string.
 *
 * The SQL may be just a constant expression, or it may be an alternating
 * list of literal parts an column parts, in which case the actual SQL
 * expression is formed by concatenating all parts, renaming the
 * columns if necessary.
 *
 * @author Richard Cyganiak (richard@cyganiak.de)
 */
public class SQLExpression extends Expression {

	/**
	 * Only usable for expressions that don't mention any columns
	 */
	public static Expression create(String sql, GenericType dataType) {
		sql = sql.trim();
		if ("1".equals(sql)) {
			return Expression.TRUE;
		}
		if ("0".equals(sql)) {
			return Expression.FALSE;
		}
		return SQLExpression.create(Collections.singletonList(sql),
				null, dataType);
	}

	/**
	 * Creates a SQL expression that may contain column references.
	 * The actual SQL expression is obtained by alternating a literal
	 * part with a column part. There must be one more literal parts
	 * than column parts.
	 */
	public static SQLExpression create(List<String> literalParts,
			List<ColumnName> columns, GenericType dataType) {
		if (columns == null) columns = Collections.emptyList();
		if (literalParts.size() != columns.size() + 1) {
			throw new IllegalArgumentException("Must have one more literal part than column parts");
		}
		return new SQLExpression(literalParts, columns, dataType);
	}

	private final List<String> literalParts;
	private final List<ColumnName> columns;
	private final Set<ColumnName> columnsAsSet;
	private final GenericType dataType;
	private final String asString;

	private SQLExpression(List<String> literalParts, List<ColumnName> columns,
			GenericType dataType) {
		this.literalParts = literalParts;
		this.columns = columns;
		this.columnsAsSet = new HashSet<ColumnName>(columns);
		this.dataType = dataType;
		this.asString = "SQL" + toSQL(null, Vendor.SQL92);
	}

	public boolean isTrue() {
		return false;
	}

	public boolean isFalse() {
		return false;
	}

	public boolean isConstant() {
		// As far as we know, the SQL expression may involve some columns,
		// and therefore not be constant throughout the table
		return false;
	}

	public boolean isConstantColumn(ColumnName column, boolean constIfTrue,
			boolean constIfFalse, boolean constIfConstantValue) {
		return false;
	}

	public Set<ColumnName> getColumns() {
		return this.columnsAsSet;
	}

	public Expression rename(Renamer renamer) {
		return new SQLExpression(literalParts, renamer.applyToColumns(columns), dataType);
	}

	public Expression substitute(ColumnName column, Expression substitution) {
		if (!columns.contains(column)) return this;
		throw new UnsupportedOperationException("Substitution of columns (" +
				column + ") in SQLExpressions not implemented: " + this.toString());
	}

	public String toSQL(DatabaseOp table, Vendor vendor) {
		StringBuffer result = new StringBuffer("(");
		for (int i = 0; i < columns.size(); i++) {
			result.append(literalParts.get(i));
			result.append(vendor.toString(columns.get(i)));
		}
		result.append(literalParts.get(literalParts.size() - 1));
		result.append(")");
		return result.toString();
	}

	public DataType getDataType(DatabaseOp table, Vendor vendor) {
		return dataType.dataTypeFor(vendor);
	}

	public String toString() {
		return asString;
	}

	public boolean equals(Object other) {
		if (!(other instanceof SQLExpression)) {
			return false;
		}
		SQLExpression otherExpression = (SQLExpression) other;
		return literalParts.equals(otherExpression.literalParts) &&
				columns.equals(otherExpression.columns) &&
				dataType.equals(otherExpression.dataType);
	}

	public int hashCode() {
		return literalParts.hashCode() ^ columns.hashCode() ^ dataType.hashCode() ^ 6543;
	}
}


text:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:context=".TestActivity$PlaceholderFragment">

    <LinearLayout style="@style/Container">

        <Button
            android:id="@+id/users_get"
            style="@style/Button"
            android:text="@string/users_get"/>

        <Button
            android:id="@+id/friends_get"
            style="@style/Button"
            android:text="@string/friends_get"/>

        <Button
            android:id="@+id/messages_get"
            style="@style/Button"
            android:text="@string/messages_get"/>

        <Button
            android:id="@+id/dialogs_get"
            style="@style/Button"
            android:text="@string/dialogs_get"/>

        <Button
            android:id="@+id/captcha_force"
            style="@style/Button"
            android:text="@string/captcha_force"/>

        <Button
            android:id="@+id/wall_post"
            style="@style/Button"
            android:text="@string/wall_post"/>

        <Button
            android:id="@+id/wall_getById"
            style="@style/Button"
            android:text="@string/wall_getById"/>

        <Button
            android:id="@+id/upload_photo"
            style="@style/Button"
            android:text="@string/upload_photo"/>

        <Button
            android:id="@+id/upload_photo_to_wall"
            style="@style/Button"
            android:text="@string/upload_photo_to_wall"/>

        <Button
            android:id="@+id/upload_several_photos_to_wall"
            style="@style/Button"
            android:text="@string/upload_several_photos_to_wall"/>

        <Button
            android:id="@+id/upload_doc"
            style="@style/Button"
            android:text="@string/upload_doc"/>

        <Button
            android:id="@+id/test_validation"
            style="@style/Button"
            android:text="@string/test_validation"/>

        <Button
            android:id="@+id/test_share"
            style="@style/Button"
            android:text="@string/test_share"/>

        <Button
            android:id="@+id/test_send_request"
            style="@style/Button"
            android:text="@string/test_send_request"/>
    </LinearLayout>
</ScrollView>


text:
package org.apache.activemq.artemis.jdbc.store.journal;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.core.journal.EncodingSupport;
import org.apache.activemq.artemis.core.journal.IOCompletion;
import org.apache.activemq.artemis.core.persistence.Persister;
import org.apache.activemq.artemis.core.journal.RecordInfo;
import org.apache.activemq.artemis.journal.ActiveMQJournalLogger;
import org.apache.activemq.artemis.utils.ActiveMQBufferInputStream;

class JDBCJournalRecord {
   /*
   Database Table Schema:

   id BIGINT (long)
   recordType SMALLINT (byte)
   compactCount SMALLINT (byte)
   txId BIGINT (long)
   userRecordType SMALLINT (byte)
   variableSize INT (int)
   record BLOB (InputStream)
   txDataSize INT (int)
   txData BLOB (InputStream)
   txCheckNoRecords INT (int)
   */

   // Record types taken from Journal Impl
   static final byte ADD_RECORD = 11;
   static final byte UPDATE_RECORD = 12;
   static final byte ADD_RECORD_TX = 13;
   static final byte UPDATE_RECORD_TX = 14;

   static final byte DELETE_RECORD_TX = 15;
   static final byte DELETE_RECORD = 16;

   static final byte PREPARE_RECORD = 17;
   static final byte COMMIT_RECORD = 18;
   static final byte ROLLBACK_RECORD = 19;

   // Callback and sync operations
   private IOCompletion ioCompletion = null;
   private boolean storeLineUp = true;
   private boolean sync = false;

   // DB Fields for all records
   private Long id;
   private byte recordType;
   private byte compactCount;
   private long txId;

   // DB fields for ADD_RECORD(TX), UPDATE_RECORD(TX),
   private int variableSize;
   protected byte userRecordType;
   private InputStream record;

   // DB Fields for PREPARE_RECORD
   private int txDataSize;
   private InputStream txData;

   // DB Fields for COMMIT_RECORD and PREPARE_RECORD
   private int txCheckNoRecords;

   private boolean isUpdate;

   private boolean isTransactional;

   private long seq;

   JDBCJournalRecord(long id, byte recordType, long seq) {
      this.id = id;
      this.recordType = recordType;

      isUpdate = recordType == UPDATE_RECORD || recordType == UPDATE_RECORD_TX;
      isTransactional = recordType == UPDATE_RECORD_TX || recordType == ADD_RECORD_TX || recordType == DELETE_RECORD_TX;

      // set defaults
      compactCount = 0;
      txId = 0;
      variableSize = 0;
      userRecordType = -1;
      record = new ByteArrayInputStream(new byte[0]);
      txDataSize = 0;
      txData = new ByteArrayInputStream(new byte[0]);
      txCheckNoRecords = 0;

      this.seq = seq;
   }

   public void complete(boolean success) {
      if (ioCompletion != null) {
         if (success) {
            ioCompletion.done();
         } else {
            ioCompletion.onError(ActiveMQExceptionType.IO_ERROR.getCode(), "JDBC Transaction failed.");
         }
      }
   }

   public void storeLineUp() {
      if (storeLineUp && ioCompletion != null) {
         ioCompletion.storeLineUp();
      }
   }

   void writeRecord(PreparedStatement statement) throws Exception {

      byte[] recordBytes = new byte[variableSize];
      byte[] txDataBytes = new byte[txDataSize];

      try {
         record.read(recordBytes);
         txData.read(txDataBytes);
      } catch (IOException e) {
         ActiveMQJournalLogger.LOGGER.error("Error occurred whilst reading Journal Record", e);
         throw e;
      }

      statement.setLong(1, id);
      statement.setByte(2, recordType);
      statement.setByte(3, compactCount);
      statement.setLong(4, txId);
      statement.setByte(5, userRecordType);
      statement.setInt(6, variableSize);
      statement.setBytes(7, recordBytes);
      statement.setInt(8, txDataSize);
      statement.setBytes(9, txDataBytes);
      statement.setInt(10, txCheckNoRecords);
      statement.setLong(11, seq);
      statement.addBatch();
   }

   void writeDeleteRecord(PreparedStatement deleteStatement) throws SQLException {
      deleteStatement.setLong(1, id);
      deleteStatement.addBatch();
   }

   static JDBCJournalRecord readRecord(ResultSet rs) throws SQLException {
      JDBCJournalRecord record = new JDBCJournalRecord(rs.getLong(1), (byte) rs.getShort(2), rs.getLong(11));
      record.setCompactCount((byte) rs.getShort(3));
      record.setTxId(rs.getLong(4));
      record.setUserRecordType((byte) rs.getShort(5));
      record.setVariableSize(rs.getInt(6));
      record.setRecord(rs.getBytes(7));
      record.setTxDataSize(rs.getInt(8));
      record.setTxData(rs.getBytes(9));
      record.setTxCheckNoRecords(rs.getInt(10));
      return record;
   }

   IOCompletion getIoCompletion() {
      return ioCompletion;
   }

   void setIoCompletion(IOCompletion ioCompletion) {
      this.ioCompletion = ioCompletion;
   }

   public void setStoreLineUp(boolean storeLineUp) {
      this.storeLineUp = storeLineUp;
   }

   public boolean isSync() {
      return sync;
   }

   public void setSync(boolean sync) {
      this.sync = sync;
   }

   public Long getId() {
      return id;
   }

   public byte getRecordType() {
      return recordType;
   }

   byte getCompactCount() {
      return compactCount;
   }

   private void setCompactCount(byte compactCount) {
      this.compactCount = compactCount;
   }

   long getTxId() {
      return txId;
   }

   void setTxId(long txId) {
      this.txId = txId;
   }

   private void setVariableSize(int variableSize) {
      this.variableSize = variableSize;
   }

   public byte getUserRecordType() {
      return userRecordType;
   }

   public void setUserRecordType(byte userRecordType) {
      this.userRecordType = userRecordType;
   }

   public void setRecord(byte[] record) {
      if (record != null) {
         this.variableSize = record.length;
         this.record = new ByteArrayInputStream(record);
      }
   }

   public void setRecord(InputStream record) {
      this.record = record;
   }

   public void setRecord(Persister persister, Object record) {
      this.variableSize = persister.getEncodeSize(record);

      ActiveMQBuffer encodedBuffer = ActiveMQBuffers.fixedBuffer(variableSize);
      persister.encode(encodedBuffer, record);
      this.record = new ActiveMQBufferInputStream(encodedBuffer);
   }

   public InputStream getRecord() {
      return record;
   }

   int getTxCheckNoRecords() {
      return txCheckNoRecords;
   }

   private void setTxCheckNoRecords(int txCheckNoRecords) {
      this.txCheckNoRecords = txCheckNoRecords;
   }

   private void setTxDataSize(int txDataSize) {
      this.txDataSize = txDataSize;
   }

   void setTxData(EncodingSupport txData) {
      this.txDataSize = txData.getEncodeSize();

      ActiveMQBuffer encodedBuffer = ActiveMQBuffers.fixedBuffer(txDataSize);
      txData.encode(encodedBuffer);
      this.txData = new ActiveMQBufferInputStream(encodedBuffer);
   }

   void setTxData(byte[] txData) {
      if (txData != null) {
         this.txDataSize = txData.length;
         this.txData = new ByteArrayInputStream(txData);
      }
   }

   public boolean isUpdate() {
      return isUpdate;
   }

   private byte[] getRecordData() throws IOException {
      byte[] data = new byte[variableSize];
      record.read(data);
      return data;
   }

   byte[] getTxDataAsByteArray() throws IOException {
      byte[] data = new byte[txDataSize];
      txData.read(data);
      return data;
   }

   RecordInfo toRecordInfo() throws IOException {
      return new RecordInfo(getId(), getUserRecordType(), getRecordData(), isUpdate(), getCompactCount());
   }

   public boolean isTransactional() {
      return isTransactional;
   }

   long getSeq() {
      return seq;
   }

   @Override
   public String toString() {
      return "JDBCJournalRecord{" +
         "compactCount=" + compactCount +
         ", id=" + id +
         ", isTransactional=" + isTransactional +
         ", isUpdate=" + isUpdate +
         ", recordType=" + recordType +
         ", seq=" + seq +
         ", storeLineUp=" + storeLineUp +
         ", sync=" + sync +
         ", txCheckNoRecords=" + txCheckNoRecords +
         ", txDataSize=" + txDataSize +
         ", txId=" + txId +
         ", userRecordType=" + userRecordType +
         ", variableSize=" + variableSize +
         '}';
   }
}


text:
template<
    typename TState
>
TState & StateConnection< TState >::getState()
{
    return dynamic_cast< StateServer< TState > * >( m_server )->getState();
}

#endif


text:
package org.semagrow.sevod.scraper.rdf.dump.legacy.handler;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.rio.RDFHandlerException;
import org.eclipse.rdf4j.rio.helpers.RDFHandlerBase;
import org.semagrow.sevod.scraper.rdf.dump.extractor.PatternExtractor;
import org.semagrow.sevod.scraper.rdf.dump.extractor.TriePatternExtractor;
import org.apache.log4j.Logger;

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

/**
 * Created by antonis on 15/5/2015.
 */
@Deprecated
public class ObjectHandler extends RDFHandlerBase {

    final private Logger log = Logger.getLogger(ObjectHandler.class);

    private PatternExtractor Objects = null;
    private List<String> patterns = new ArrayList<>();

    public ObjectHandler(int bound) {
        Objects = new TriePatternExtractor(bound);
    }

    @Override
    public void startRDF() throws RDFHandlerException {
        super.startRDF();
    }

    @Override
    public void handleStatement(Statement st) throws RDFHandlerException {
        log.debug("Handling statement " + st.toString());
        if (st.getObject() instanceof IRI) {
            String str = ((IRI) st.getObject()).toString();
            Objects.addString(str);
        }
    }

    @Override
    public void endRDF() throws RDFHandlerException {
        patterns = new ArrayList<>(Objects.getPatterns());
        log.debug("Found " + patterns.size() + " object patterns " + patterns);
        super.endRDF();
    }

    public List<String> getPatterns() {
        return patterns;
    }

    private void printPrefixes() {
        Collections.sort(patterns);
        for (String s : patterns) {
            System.out.println(s);
        }
    }
}


text:
#include "SkGpuBlurUtils.h"

#include "SkRect.h"

#if SK_SUPPORT_GPU
#include "effects/GrConvolutionEffect.h"
#include "effects/GrTextureDomainEffect.h"
#include "GrContext.h"
#endif

namespace SkGpuBlurUtils {

#if SK_SUPPORT_GPU

#define MAX_BLUR_SIGMA 4.0f

static void scale_rect(SkRect* rect, float xScale, float yScale) {
    rect->fLeft   = SkScalarMul(rect->fLeft,   SkFloatToScalar(xScale));
    rect->fTop    = SkScalarMul(rect->fTop,    SkFloatToScalar(yScale));
    rect->fRight  = SkScalarMul(rect->fRight,  SkFloatToScalar(xScale));
    rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
}

static float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
    *scaleFactor = 1;
    while (sigma > MAX_BLUR_SIGMA) {
        *scaleFactor *= 2;
        sigma *= 0.5f;
    }
    *radius = static_cast<int>(ceilf(sigma * 3.0f));
    GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
    return sigma;
}

static void convolve_gaussian_pass(GrContext* context,
                                   const SkRect& srcRect,
                                   const SkRect& dstRect,
                                   GrTexture* texture,
                                   Gr1DKernelEffect::Direction direction,
                                   int radius,
                                   float sigma,
                                   bool useBounds,
                                   float bounds[2]) {
    GrPaint paint;
    paint.reset();
    SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(
        texture, direction, radius, sigma, useBounds, bounds));
    paint.reset();
    paint.addColorEffect(conv);
    context->drawRectToRect(paint, dstRect, srcRect);
}

static void convolve_gaussian(GrContext* context,
                              const SkRect& srcRect,
                              const SkRect& dstRect,
                              GrTexture* texture,
                              Gr1DKernelEffect::Direction direction,
                              int radius,
                              float sigma,
                              bool cropToSrcRect) {
    float bounds[2] = { 0.0f, 1.0f };
    if (!cropToSrcRect) {
        convolve_gaussian_pass(context, srcRect, dstRect, texture,
                          direction, radius, sigma, false, bounds);
        return;
    }
    SkRect lowerSrcRect = srcRect, lowerDstRect = dstRect;
    SkRect middleSrcRect = srcRect, middleDstRect = dstRect;
    SkRect upperSrcRect = srcRect, upperDstRect = dstRect;
    SkScalar size;
    SkScalar rad = SkIntToScalar(radius);
    if (direction == Gr1DKernelEffect::kX_Direction) {
        bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width();
        bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width();
        size = srcRect.width();
        lowerSrcRect.fRight = srcRect.left() + rad;
        lowerDstRect.fRight = dstRect.left() + rad;
        upperSrcRect.fLeft = srcRect.right() - rad;
        upperDstRect.fLeft = dstRect.right() - rad;
        middleSrcRect.inset(rad, 0);
        middleDstRect.inset(rad, 0);
    } else {
        bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height();
        bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height();
        size = srcRect.height();
        lowerSrcRect.fBottom = srcRect.top() + rad;
        lowerDstRect.fBottom = dstRect.top() + rad;
        upperSrcRect.fTop = srcRect.bottom() - rad;
        upperDstRect.fTop = dstRect.bottom() - rad;
        middleSrcRect.inset(0, rad);
        middleDstRect.inset(0, rad);
    }
    if (radius >= size * SK_ScalarHalf) {
        // Blur radius covers srcRect; use bounds over entire draw
        convolve_gaussian_pass(context, srcRect, dstRect, texture,
                          direction, radius, sigma, true, bounds);
    } else {
        // Draw upper and lower margins with bounds; middle without.
        convolve_gaussian_pass(context, lowerSrcRect, lowerDstRect, texture,
                          direction, radius, sigma, true, bounds);
        convolve_gaussian_pass(context, upperSrcRect, upperDstRect, texture,
                          direction, radius, sigma, true, bounds);
        convolve_gaussian_pass(context, middleSrcRect, middleDstRect, texture,
                          direction, radius, sigma, false, bounds);
    }
}

GrTexture* GaussianBlur(GrContext* context,
                        GrTexture* srcTexture,
                        bool canClobberSrc,
                        const SkRect& rect,
                        bool cropToRect,
                        float sigmaX,
                        float sigmaY) {
    GrAssert(NULL != context);

    GrContext::AutoRenderTarget art(context);

    GrContext::AutoMatrix am;
    am.setIdentity(context);

    SkIRect clearRect;
    int scaleFactorX, radiusX;
    int scaleFactorY, radiusY;
    sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
    sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);

    SkRect srcRect(rect);
    scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
    srcRect.roundOut();
    scale_rect(&srcRect, static_cast<float>(scaleFactorX),
                         static_cast<float>(scaleFactorY));

    GrContext::AutoClip acs(context, SkRect::MakeWH(srcRect.width(), srcRect.height()));

    GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
             kRGBA_8888_GrPixelConfig == srcTexture->config() ||
             kAlpha_8_GrPixelConfig == srcTexture->config());

    GrTextureDesc desc;
    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
    desc.fWidth = SkScalarFloorToInt(srcRect.width());
    desc.fHeight = SkScalarFloorToInt(srcRect.height());
    desc.fConfig = srcTexture->config();

    GrAutoScratchTexture temp1, temp2;
    GrTexture* dstTexture = temp1.set(context, desc);
    GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(context, desc);
    if (NULL == dstTexture || NULL == tempTexture) {
        return NULL;
    }

    for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
        GrPaint paint;
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect(srcRect);
        if (cropToRect && i == 1) {
            dstRect.offset(-dstRect.fLeft, -dstRect.fTop);
            SkRect domain;
            matrix.mapRect(&domain, rect);
            domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width() : 0.0f,
                         i < scaleFactorY ? SK_ScalarHalf / srcTexture->height() : 0.0f);
            SkAutoTUnref<GrEffectRef> effect(GrTextureDomainEffect::Create(
                srcTexture,
                matrix,
                domain,
                GrTextureDomainEffect::kDecal_WrapMode,
                GrTextureParams::kBilerp_FilterMode));
            paint.addColorEffect(effect);
        } else {
            GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
            paint.addColorTextureEffect(srcTexture, matrix, params);
        }
        scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
                             i < scaleFactorY ? 0.5f : 1.0f);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }

    SkIRect srcIRect;
    srcRect.roundOut(&srcIRect);

    if (sigmaX > 0.0f) {
        if (scaleFactorX > 1) {
            // Clear out a radius to the right of the srcRect to prevent the
            // X convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                          radiusX, srcIRect.height());
            context->clear(&clearRect, 0x0);
        }
        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcRect, dstRect, srcTexture,
                          Gr1DKernelEffect::kX_Direction, radiusX, sigmaX, cropToRect);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (sigmaY > 0.0f) {
        if (scaleFactorY > 1 || sigmaX > 0.0f) {
            // Clear out a radius below the srcRect to prevent the Y
            // convolution from reading garbage.
            clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                          srcIRect.width(), radiusY);
            context->clear(&clearRect, 0x0);
        }

        context->setRenderTarget(dstTexture->asRenderTarget());
        SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
        convolve_gaussian(context, srcRect, dstRect, srcTexture,
                          Gr1DKernelEffect::kY_Direction, radiusY, sigmaY, cropToRect);
        srcTexture = dstTexture;
        srcRect = dstRect;
        SkTSwap(dstTexture, tempTexture);
    }

    if (scaleFactorX > 1 || scaleFactorY > 1) {
        // Clear one pixel to the right and below, to accommodate bilinear
        // upsampling.
        clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
                                      srcIRect.width() + 1, 1);
        context->clear(&clearRect, 0x0);
        clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
                                      1, srcIRect.height());
        context->clear(&clearRect, 0x0);
        SkMatrix matrix;
        matrix.setIDiv(srcTexture->width(), srcTexture->height());
        context->setRenderTarget(dstTexture->asRenderTarget());

        GrPaint paint;
        // FIXME:  this should be mitchell, not bilinear.
        GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode);
        paint.addColorTextureEffect(srcTexture, matrix, params);

        SkRect dstRect(srcRect);
        scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
        context->drawRectToRect(paint, dstRect, srcRect);
        srcRect = dstRect;
        srcTexture = dstTexture;
        SkTSwap(dstTexture, tempTexture);
    }
    if (srcTexture == temp1.texture()) {
        return temp1.detach();
    } else if (srcTexture == temp2.texture()) {
        return temp2.detach();
    } else {
        srcTexture->ref();
        return srcTexture;
    }
}
#endif

}


text:
\chapter{IdGen API}
\index{IdGen API}
\input{api/idgen/info}
\section{GetIdGenConfigs}
\index{GetIdGenConfigs}
\label{Api:GetIdGenConfigs}
\begin{lstlisting}[style=nonumbers]
   List<RaptureIdGenConfig> getIdGenConfigs (
           String    authority
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.getIdGenConfigs(authority);
%\end{lstlisting}
\input{api/idgen/getIdGenConfigs}

\rule{12cm}{2pt}
\section{GetIdGenConfig}
\index{GetIdGenConfig}
\label{Api:GetIdGenConfig}
\begin{lstlisting}[style=nonumbers]
   RaptureIdGenConfig getIdGenConfig (
           String    idGenUri
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.getIdGenConfig(idGenUri);
%\end{lstlisting}
\input{api/idgen/getIdGenConfig}

\rule{12cm}{2pt}
\section{CreateIdGen}
\index{CreateIdGen}
\label{Api:CreateIdGen}
\begin{lstlisting}[style=nonumbers]
   RaptureIdGenConfig createIdGen (
           String    idGenUri
           String    config
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.createIdGen(idGenUri,config);
%\end{lstlisting}
\input{api/idgen/createIdGen}

\rule{12cm}{2pt}
\section{IdGenExists}
\index{IdGenExists}
\label{Api:IdGenExists}
\begin{lstlisting}[style=nonumbers]
   boolean idGenExists (
           String    idGenUri
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.idGenExists(idGenUri);
%\end{lstlisting}
\input{api/idgen/idGenExists}

\rule{12cm}{2pt}
\section{DeleteIdGen}
\index{DeleteIdGen}
\label{Api:DeleteIdGen}
\begin{lstlisting}[style=nonumbers]
   void deleteIdGen (
           String    idGenUri
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.deleteIdGen(idGenUri);
%\end{lstlisting}
\input{api/idgen/deleteIdGen}

\rule{12cm}{2pt}
\section{SetIdGen}
\index{SetIdGen}
\label{Api:SetIdGen}
\begin{lstlisting}[style=nonumbers]
   void setIdGen (
           String    idGenUri
           Long    count
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.setIdGen(idGenUri,count);
%\end{lstlisting}
\input{api/idgen/setIdGen}

\rule{12cm}{2pt}
\section{Next}
\index{Next}
\label{Api:Next}
\begin{lstlisting}[style=nonumbers]
   String next (
           String    idGenUri
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.next(idGenUri);
%\end{lstlisting}
\input{api/idgen/next}

\rule{12cm}{2pt}
\section{NextIds}
\index{NextIds}
\label{Api:NextIds}
\begin{lstlisting}[style=nonumbers]
   String nextIds (
           String    idGenUri
           Long    num
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/idgen
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.nextIds(idGenUri,num);
%\end{lstlisting}
\input{api/idgen/nextIds}

\rule{12cm}{2pt}
\section{SetupDefaultIdGens}
\index{SetupDefaultIdGens}
\label{Api:SetupDefaultIdGens}
\begin{lstlisting}[style=nonumbers]
   void setupDefaultIdGens (
           boolean    force
   )
\end{lstlisting}
\begin{Verbatim}[formatcom=\color{Maroon}]
  Entitlement: /admin/lock
\end{Verbatim}
%\begin{lstlisting}[language=reflex]
%ret = #idgen.setupDefaultIdGens(force);
%\end{lstlisting}
\input{api/idgen/setupDefaultIdGens}

\rule{12cm}{2pt}


text:
namespace Erwine.Leonard.T.WordServer.WordNetDataReader
{
    public class SynsetPointer
    {
        public Common.PointerSymbol PointerSymbol { get; set; }
        public long SynsetOffset { get; set; }
        public Common.PartOfSpeech PartOfSpeech { get; set; }
        public short Source { get; set; }
        public short Target { get; set; }

        public SynsetPointer(Common.PointerSymbol pointer_symbol, long synset_offset, Common.PartOfSpeech pos, short source, short target)
        {
            this.PointerSymbol = pointer_symbol;
            this.SynsetOffset = synset_offset;
            this.PartOfSpeech = pos;
            this.Source = source;
            this.Target = target;
        }
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
  <test name="Test">
  		<classes>
	       <class name="com.sample.SearchTest" />
	    </classes>
  </test> <!-- Test -->
</suite> <!-- Suite -->


text:
package internalversion

import (
	federation "k8s.io/kubernetes/federation/apis/federation"
	api "k8s.io/kubernetes/pkg/api"
	restclient "k8s.io/kubernetes/pkg/client/restclient"
	watch "k8s.io/kubernetes/pkg/watch"
)

// ClustersGetter has a method to return a ClusterInterface.
// A group's client should implement this interface.
type ClustersGetter interface {
	Clusters() ClusterInterface
}

// ClusterInterface has methods to work with Cluster resources.
type ClusterInterface interface {
	Create(*federation.Cluster) (*federation.Cluster, error)
	Update(*federation.Cluster) (*federation.Cluster, error)
	UpdateStatus(*federation.Cluster) (*federation.Cluster, error)
	Delete(name string, options *api.DeleteOptions) error
	DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error
	Get(name string) (*federation.Cluster, error)
	List(opts api.ListOptions) (*federation.ClusterList, error)
	Watch(opts api.ListOptions) (watch.Interface, error)
	Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *federation.Cluster, err error)
	ClusterExpansion
}

// clusters implements ClusterInterface
type clusters struct {
	client restclient.Interface
}

// newClusters returns a Clusters
func newClusters(c *FederationClient) *clusters {
	return &clusters{
		client: c.RESTClient(),
	}
}

// Create takes the representation of a cluster and creates it.  Returns the server's representation of the cluster, and an error, if there is any.
func (c *clusters) Create(cluster *federation.Cluster) (result *federation.Cluster, err error) {
	result = &federation.Cluster{}
	err = c.client.Post().
		Resource("clusters").
		Body(cluster).
		Do().
		Into(result)
	return
}

// Update takes the representation of a cluster and updates it. Returns the server's representation of the cluster, and an error, if there is any.
func (c *clusters) Update(cluster *federation.Cluster) (result *federation.Cluster, err error) {
	result = &federation.Cluster{}
	err = c.client.Put().
		Resource("clusters").
		Name(cluster.Name).
		Body(cluster).
		Do().
		Into(result)
	return
}

func (c *clusters) UpdateStatus(cluster *federation.Cluster) (result *federation.Cluster, err error) {
	result = &federation.Cluster{}
	err = c.client.Put().
		Resource("clusters").
		Name(cluster.Name).
		SubResource("status").
		Body(cluster).
		Do().
		Into(result)
	return
}

// Delete takes name of the cluster and deletes it. Returns an error if one occurs.
func (c *clusters) Delete(name string, options *api.DeleteOptions) error {
	return c.client.Delete().
		Resource("clusters").
		Name(name).
		Body(options).
		Do().
		Error()
}

// DeleteCollection deletes a collection of objects.
func (c *clusters) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error {
	return c.client.Delete().
		Resource("clusters").
		VersionedParams(&listOptions, api.ParameterCodec).
		Body(options).
		Do().
		Error()
}

// Get takes name of the cluster, and returns the corresponding cluster object, and an error if there is any.
func (c *clusters) Get(name string) (result *federation.Cluster, err error) {
	result = &federation.Cluster{}
	err = c.client.Get().
		Resource("clusters").
		Name(name).
		Do().
		Into(result)
	return
}

// List takes label and field selectors, and returns the list of Clusters that match those selectors.
func (c *clusters) List(opts api.ListOptions) (result *federation.ClusterList, err error) {
	result = &federation.ClusterList{}
	err = c.client.Get().
		Resource("clusters").
		VersionedParams(&opts, api.ParameterCodec).
		Do().
		Into(result)
	return
}

// Watch returns a watch.Interface that watches the requested clusters.
func (c *clusters) Watch(opts api.ListOptions) (watch.Interface, error) {
	return c.client.Get().
		Prefix("watch").
		Resource("clusters").
		VersionedParams(&opts, api.ParameterCodec).
		Watch()
}

// Patch applies the patch and returns the patched cluster.
func (c *clusters) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *federation.Cluster, err error) {
	result = &federation.Cluster{}
	err = c.client.Patch(pt).
		Resource("clusters").
		SubResource(subresources...).
		Name(name).
		Body(data).
		Do().
		Into(result)
	return
}


text:
<!doctype html>

		<meta charset="utf-8">

		<title>Introduction to GraphQL</title>

		<meta name="description" content="An introduction to GraphQL and how it is distinguished from extant RESTful paradigms">
		<meta name="author" content="Preston So">

		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />

		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">

		<link rel="stylesheet" href="css/reveal.css">
		<link rel="stylesheet" href="css/theme/night.css" id="theme">

		<link rel="stylesheet" href="lib/css/zenburn.css">

Introduction to GraphQL

Preston So

						prestonso • @prestonso • preston.so

Presented at

BADCamp 2015 (October 25, 2015)

NYC Drupal Meetup (February 3, 2016)

Welcome!

						Preston So has designed and developed websites since 2001 and built them in Drupal since 2007. He is Development Manager of Acquia Labs at Acquia and co-founder of the Southern Colorado Drupal User Group (est. 2008). Previously, Preston was Technical Lead of Entertainment Weekly at Time Inc.

What we'll cover

Origins and motivations

GraphQL and REST

GraphQL syntax

Types and schemas

GraphQL and Drupal

Origins and motivations

What is GraphQL?

The Facebook open-source ecosystem

History of GraphQL

A quick introduction to React

React, Relay, and GraphQL

What is GraphQL?

							GraphQL is a declarative query language and an application-level protocol.

The Facebook open-source ecosystem

							React is a view-based JavaScript framework that uses a Virtual DOM to save application state and rerenders components of the view based on diffed states.

The Facebook open-source ecosystem

							Relay is a framework that juxtaposes data fetching needs and React components in the same place; in other words, Relay connects view logic to queries in the back end.

The Facebook open-source ecosystem

							GraphQL is a query language that enables transport- and storage-agnostic communication and returns data according to the same structure as the request query.

History of GraphQL

Invented during the conversion of HTML5-based mobile apps into native apps

Facilitates most interactions in the iOS and Android Facebook applications

Predates Relay by three years

History of GraphQL

							Instead of placing data fetching logic in some other part of the client application – or embedding this logic in a custom endpoint on the server – we instead co-locate a declarative data-fetching specification alongside the React component.

—Nick Shrock

History of GraphQL

Client requests and server payloads adhere to a shared shape.

The client dictates what the server provides. Each component declares what it needs.

A quick introduction to React

							Let's take a React application that needs to fetch some fields adhering to a certain structure, such as a list of articles, each alongside the following information.

Article

Title

Path

Author

Name

Location

A quick introduction to React

							React consists of components, which are rendered through JSX templates and comprise view hierarchies.

							var articleListItem = React.createClass({
  render: function () {
    return (

        {this.props.article.title}
        {this.props.article.author.name}
        from {this.props.article.author.location}

    );
  }
});

React, Relay, and GraphQL

							With GraphQL, this structure can be easily mirrored on the server in both query and response.

							var articleListItem = React.createClass({
  statics: {
    queries: {
      article: function () {
        return graphql`
          {
            article {
              title
              path
              author {
                name
                location
              }
            }
          }
        `;
      }
    }
  }
  // render: function () { ...
});

React, Relay, and GraphQL

							There's a lot of power in this approach ...

							{
  article {
    title
    path
    author {
      name
      location
    }
  }
}

React, Relay, and GraphQL

							... because the server's response really does mirror the client's desired query.

							{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse",
    "path": "http://usatoday.com/article/gang-jailed-hoverboard-rampage",
    "author": {
      "name": "Compu-Fax",
      "location": "Hill Valley, CA"
    }
  }
}

GraphQL and REST

Limitations of REST

How GraphQL resolves REST limitations

Why GraphQL?

Criticisms of GraphQL

Get going now

Limitations of REST

Many endpoints

Bloated responses

Many round trips

No backwards compatibility

Not introspective

Many endpoints

							Endpoints are specific to individual views or ill-suited for trees of related resources, leading to bespoke or ad-hoc endpoints.

Bloated responses

							Due to a REST API's changing requirements, clients that only need limited data may have to deal with increasingly large payloads destined for other clients.

GET /users/:id

GET /groups/:id

GET /groups/:id/users/:id

Many round trips

							If what is fetched for your view is complex and relational, multiple client-server round trips and corresponding bootstraps will be required, delaying render.

No backwards compatibility

							REST APIs are versioned and by nature obsolescent as client needs evolve. Queries must be rewritten against the new API.

No introspection

							REST APIs with custom endpoints usually lack a native schema or formalized type system, making client-side tooling and validation difficult.

How GraphQL resolves REST limitations

Fewer endpoints

Tailored responses

Fewer round trips

Backwards compatibility

Introspective

Fewer endpoints

							A shared endpoint can resolve GraphQL queries into root calls and send back a single, unified response.

Tailored responses

							Client-driven queries mean that the response is catered to the demands of the client rather than the limitations of the API.

Fewer round trips

							A GraphQL server returns a single response to match the request structure, which is flexible enough to accommodate many possible relationships.

Backwards compatibility

							No matter what version your most current API, your client can provide the same query to multiple versions and expect a common response.

Introspection

							GraphQL has a native and highly extensible schema and type system.

Why GraphQL?

							GraphQL is a query language that is a common vernacular between server and client, similar enough to JSON to be easy for onboarding.

Why GraphQL?

							GraphQL accelerates the arrival of your query's response by preventing unneeded requests or bootstraps of the back end.

Why GraphQL?

							GraphQL is an application-layer protocol agnostic to both its transport (the HTTP protocol is only one of many ways queries can be transmitted) and the database queried (schemas need not match).

Criticisms of GraphQL

							Different requirements for views can be satisfied by provisioning additional REST endpoints for small subsets of data. But this arbitrarily adds more endpoints.

Criticisms of GraphQL

							HTTP can handle multiple parallel network requests. But HTTP/1.1 recommends only two, while Chrome accepts six. HTTP/2 may mitigate this.

Criticisms of GraphQL

							Content negotiation in HTTP allows clients to request multiple versions of a document at a single path. This resolves the issue of requests against API versions at differing paths.

Criticisms of GraphQL

							HTTP has a built-in content type system that is analogous to GraphQL's native type system and can accompany standards such as JSON Schema.

Get going now

							Rising Stack's GraphQL server is implemented in Node.js and has MongoDB integration: github.com/RisingStack/graphql-server

GraphQL syntax

Operations and selection sets

Fields and aliases

Fragments

Variables

Directives

Mutations

Operations

							GraphQL models two types of operations.

							query {
  # Read-only fetch
}
mutation {
  # Write then fetch
}

Operations

							These operations can have names, which are case-sensitive.

							query getUser {
  # Read-only fetch
}
mutation changeUser {
  # Write then fetch
}

Operations

							Anonymous queries have a shorthand.

							{
  # Read query
}

Selection sets

							Selection sets are made up of \n-separated fields, which are discrete pieces of information.

							{
  firstName
  lastName
  email
}

Selection sets

							Selection sets are made up of \n-separated fields, which are discrete pieces of information.

							{
  "firstName": "Marty",
  "lastName": "McFly",
  "email": "marty@mcfly.net"
}

Fields

							Fields can describe relationships with other data.

							{
  # Top-level fields are typically globally accessible.
  user {
    firstName
    lastName
    email
    location {
      city
      country
    }
  }
}

Fields

							Fields can describe relationships with other data.

							{
  "user": {
    "firstName": "Marty",
    "lastName": "McFly",
    "email": "marty@mcfly.net",
    "location": {
      "city": "Hill Valley",
      "country": "USA"
    }
  }
}

Fields

							Fields are like functions insofar as they return values and can carry arguments.

							{
  user(id: 3) {
    firstName
    lastName
    email
    avatar(height: 72)
  }
}

Fields

							Fields are like functions insofar as they return values and can carry arguments.

							{
  "user": {
    "firstName": "Marty",
    "lastName": "McFly",
    "email": "marty@mcfly.net",
    "avatar": "http://cdn.mcfly.net/img/marty-72x72.jpg"
  }
}

Fields

							More than one argument is possible in an arbitrary order.

							{
  user(id: 3) {
    firstName
    lastName
    email
    avatar(height: 72, width: 72)
  }
}

Aliases

							Fields can be aliased.

							{
  admin:user(id: 1) {
    firstName
    lastName
    email
    avatar(height: 72, width: 72)
  }
}

Aliases

							Fields can be aliased.

							{
  "admin": {
    "firstName": "Doc",
    "lastName": "Brown",
    "email": "doc@docbrown.com",
    "avatar": "http://assets.docbrown.com/i/doc-72x72.jpg"
  }
}

Aliases

							Aliases are also useful for disambiguating identically named fields.

							{
  admin:user(id: 1) {
    firstName
    lastName
    email
    thumbnail:avatar(height: 72, width: 72)
    image:avatar(height: 250, width: 250)
  }
}

Aliases

							Aliases are also useful for disambiguating identically named fields.

							{
  "admin": {
    "firstName": "Doc",
    "lastName": "Brown",
    "email": "doc@docbrown.com",
    "thumbnail": "http://assets.docbrown.com/i/avatar-72x72.jpg",
    "image": "http://assets.docbrown.com/i/avatar-250x250.jpg"
  }
}

Fragments

							Fragments allow for field reuse to keep your document clean. Fields in fragments are added at the same level of invocation as adjacent fields.

							{
  article:node(id: 992) {
    title
    ...content
  }
}
fragment content on Page {
  body
}

Fragments

							Fragments allow for field reuse to keep your document clean. Fields in fragments are added at the same level of invocation as adjacent fields.

							{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse",
    "body": "Reckless hoverboarders careened into Hill Valley's City Courthouse late yesterday afternoon, causing serious damage to the structure."
  }
}

Fragments

							Fragments must declare types, which facilitate conditionally applied fields. When the object selected by the query is a Teaser, the body is excluded, and the image is shrunken.

							{
  article:node(id: 992) {
    title
    ...content
  }
}
fragment content on Page {
  image(width: 960)
  body
}
fragment content on Teaser {
  image(width: 100)
}

Fragments

							Fragments must declare types, which facilitate conditionally applied fields. When the object selected by the query is a Teaser, the body is excluded, and the image is shrunken.

							// Type is Page
{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse",
    "image": "http://i.usatoday.com/img/gang-jailed-hoverboard-rampage-960x250.jpg",
    "body": "Reckless hoverboarders careened into Hill Valley's City Courthouse late yesterday afternoon, causing serious damage to the structure."
  }
}
// Type is Teaser
{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse",
    "image": "http://i.usatoday.com/img/gang-jailed-hoverboard-rampage-100x100.jpg"
  }
}

Fragments

							Fragments can be nested.

							{
  article:node(id: 992) {
    title
    ...content
  }
}
fragment content on Page {
  ...mainImage
  body
}
fragment mainImage on Page {
  image(width: 960)
}

Fragments

							Fragments can be nested.

							{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse",
    "image": "http://i.usatoday.com/img/gang-jailed-hoverboard-rampage-960x250.jpg",
    "body": "Reckless hoverboarders careened into Hill Valley's City Courthouse late yesterday afternoon, causing serious damage to the structure."
  }
}

Inline fragments

							Fragments can be inline to improve code legibility.

							{
  article:node(id: 992) {
    title
    ...content on Page {
      body
      image(width: 960)
    }
    ...content on Teaser {
      image(width: 100)
    }
  }
}

Inline fragments

							Inline fragments can also be nameless.

							{
  article:node(id: 992) {
    title
    ... on Page {
      body
      image(width: 960)
    }
    ... on Teaser {
      image(width: 100)
    }
  }
}

Variables

							Variables can be used to maximize a query's reusability. They must be defined at the top of each operation, which also encompasses their scope.

							query getArticle($imageSize: Int) {
  article:node(id: 992) {
    title
    image(width: $imageSize)
    ... on Page {
      body
    }
  }
}

Directives

							Directives alter execution behavior and can be used to conditionally include or exclude fields.

							query getArticle($hasBody: Boolean) {
  article:node(id: 992) {
    title
    ... @include(if: $hasBody) {
      body
      image(width: 960)
    }
  }
}

Directives

							Directives alter execution behavior and can be used to conditionally include or exclude fields.

							// $hasBody resolves to false
{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse"
  }
}
// $hasBody resolves to true
{
  "article": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse",
    "body": "Reckless hoverboarders careened into Hill Valley's City Courthouse late yesterday afternoon, causing serious damage to the structure.",
    "image": "http://i.usatoday.com/img/gang-jailed-hoverboard-rampage-960x250.jpg"
  }
}

Directives

							The GraphQL spec recommends supporting @skip and @include.

							query getArticle($hasBody: Boolean, $hasAuthor: Boolean) {
  article:node(id: 992) {
    title
    author @skip(if: $hasAuthor)
    ... @include(if: $hasBody) {
      body
      image(width: 960)
    }
  }
}

Mutations

							In both queries and mutations, all fields apart from top-level mutation fields resolve idempotently.

							mutation favoriteArticle {
  favoriteArticle(id: 992) {
    node {
      favoriteCount
    }
  }
}

Mutations

							In both queries and mutations, all fields apart from top-level mutation fields resolve idempotently.

							// Server performs favoriteArticle write.
{
  "node": {
    "favoriteCount": 1022
  }
}

Mutations

							This mutation supplies a new title to a particular node before fetching the new title.

							mutation setTitle {
  setTitle(title: "Gang Jailed: Hoverboard Rampage Destroys Courthouse") {
    node(id: 992) {
      title
    }
  }
}

Mutations

							This mutation supplies a new title to a particular node before fetching the new title.

							// Before setTitle mutation
{
  "node": {
    "title": "Youth Jailed: Marty McFly Junior Arrested for Theft"
  }
}
// After setTitle mutation
{
  "node": {
    "title": "Gang Jailed: Hoverboard Rampage Destroys Courthouse"
  }
}

Types and schemas

Scalars

Objects

Object field arguments

Interfaces

Unions

Introspection

Types and schemas

							In GraphQL, schemas define the capabilities of your GraphQL server — which types and directives it supports — and validate your queries.

Scalars

							A GraphQL server should generally support these scalar types at minimum.

Int

Float

String

Boolean

ID (serialized as String)

Objects

							Types are objects that are validated against and represent the full breadth of selectable fields.

							type Node {
  title: String
  body: String
  image: Url
}

Objects

							Types can refer to other types you have created.

							type Node {
  title: String
  body: String
  image: Url
  author: User
  related: Node
}

Objects

							If a type object is nested within another, some field within the nested object must be selected. Therefore this query is valid.

							{
  title
  related {
    title
  }
}

Objects

							But this one is not.

							{
  title
  related
}

Object field arguments

							Field arguments are defined by expressing all possible arguments and expected input types.

							type Node {
  title: String
  body: String
  image(height: Int, width: Int): Url
}

Object field arguments

							Once this type object is defined, these queries are valid.

							{
  image(height: 100)
}
# New query
{
  image(height: 100, width: 100)
}

Interfaces

							Interfaces are implemented by GraphQL objects to ensure a field is always present.

							interface Titled {
  title: String
}
type Node implements Titled {
  title: String
  body: String
}
type TaxonomyTerm implements Titled {
  title: String
  vocabulary: Vocabulary
}

Interfaces

							Types invoked within type objects can refer to interfaces.

							type Metadata {
  entity: Titled
  created: Timestamp
  changed: Timestamp
}

Interfaces

							This allows for introspection.

							{
  entity {
    title
  }
  created
}

Interfaces

							If Titled is a Node, you can access its properties using a fragment.

							{
  entity {
    title
    ... on Node {
      body
    }
  }
}

Unions

							Unions in GraphQL are objects that could be one of multiple types, such as a search result.

							Union Result = Node | TaxonomyTerm

type Node {
  title: String
  body: String
}
type TaxonomyTerm {
  title: String
  vocabulary: Vocabulary
}
type Search {
  response: Result
}

Unions

							This allows for us to set type-based conditions in our queries, since Result can be either type.

							query searchQuery {
  response {
    # The following field is only valid if all Result types have title.
    title
    ... on Node {
      body
    }
    ... on TaxonomyTerm {
      vocabulary
    }
  }
}

Introspection

							GraphQL allows for exhaustive introspection of the schema. For example, take Node.

							type Node {
  title: String
  body: String
  image: Url
}

Introspection

							We can build a query selecting the built-in field __type.

							{
  __type(name: "Node") {
    name
    fields {
      name
      type {
        name
      }
    }
  }
}

Introspection

							This returns a hierarchy of the type object.

							{
  "__type": {
    "name": "Node",
    "fields": [
      {
        "name": "title",
        "type": { "name": "String" }
      },
      {
        "name": "body",
        "type": { "name": "String" }
      },
      {
        "name": "image",
        "type": { "name": "Url" }
      }
    ]
  }
}

Introspection

							You can also use the __schema field to access default types.

							{
  __schema {
    types {
      name
    }
  }
}

GraphQL and Drupal

GraphQL and Drupal 8

Next steps for GraphQL module

The future of GraphQL

Decoupled Drupal and GraphQL

Up for discussion

GraphQL and Drupal 8

							Sebastian Siemssen (fubhy) was featured in the Barcelona Driesnote and is currently working on a GraphQL implementation on Drupal within the native entity system.

							d.o/project/graphql

GraphQL and Drupal 8

The module is not currently installable, as it depends on a PHP library which needs further work. It will soon be open-sourced with documentation on GitHub.

GraphiQL is a GUI for testing and debugging queries.

GraphQL and Drupal 8

Video demo

Next steps for module

Access control

Mutation support

Schema and type configurability

The future of GraphQL

The spec is in heavy flux (no pun intended). Features are still being added.

Facebook plans to build more tools that natively support GraphQL.

Websocket support was announced in recent days, and details will soon be added to the spec and to the JavaScript reference implementation on GitHub.

Decoupled Drupal and GraphQL

Developers of Drupal-backed React applications will see benefit earlier, but since GraphQL is transport-agnostic, any application built on a client-side framework can submit queries.

A GraphQL server in Drupal could serve clients lightweight responses in one bootstrap.

The same server could interpret many different query structures and tailor responses.

Up for discussion

What is the future of technologies like GraphQL? What about Netflix's Falcor?

What is the future of Web Services in Drupal in light of GraphQL? Should we prioritize implementation of a GraphQL server?

What is the future of decoupled architectures in the front end with GraphQL?

What is the future of RESTful architectures and the server-client relationship in light of GraphQL?

Thank you!

						prestonso • @prestonso • preston.so