gt:         if (isExpectedResponse(somePacket.getPacketType())) {
context: /**
   * Copyright (c) 2014-2017 by the respective copyright holders.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   */
  package org.eclipse.smarthome.binding.lifx.internal.protocol;
  
  import java.nio.ByteBuffer;
  
  import org.eclipse.smarthome.binding.lifx.internal.fields.ByteField;
  import org.eclipse.smarthome.binding.lifx.internal.fields.Field;
  import org.eclipse.smarthome.binding.lifx.internal.fields.MACAddress;
  import org.eclipse.smarthome.binding.lifx.internal.fields.MACAddressField;
  import org.eclipse.smarthome.binding.lifx.internal.fields.UInt16Field;
  import org.eclipse.smarthome.binding.lifx.internal.fields.UInt32Field;
  import org.eclipse.smarthome.binding.lifx.internal.fields.UInt8Field;
  
  /**
   * Represents an abstract packet, providing conversion functionality to and from
   * {@link ByteBuffer}s for common packet (preamble) fields. Subtypes of this
   * class can provide conversion functionality for specialized fields.
   *
   * <p>
   * Defining new packet types essentially involves extending this class,
   * defining the fields and implementing {@link #packetType()},
   * {@link #packetLength()}, and {@link #packetBytes()}. By convention, packet
   * type should be stored in a {@code public static final int PACKET_TYPE} field
   * in each subtype, followed by a listing of fields contained in the packet.
   * Field definitions should remain accessible to outside classes in the event
   * they need to worked with directly elsewhere.
   *
   * @author Tim Buckley - Initial Contribution
   * @author Karel Goderis - Enhancement for the V2 LIFX Firmware and LAN Protocol Specification
   */
  public abstract class Packet {
  
      public static final Field<Integer> FIELD_SIZE = new UInt16Field().little();
      public static final Field<Integer> FIELD_PROTOCOL = new UInt16Field().little();
      public static final Field<Long> FIELD_SOURCE = new UInt32Field().little();
      public static final Field<MACAddress> FIELD_TARGET = new MACAddressField();
      public static final Field<ByteBuffer> FIELD_RESERVED_1 = new ByteField(6);
      public static final Field<Integer> FIELD_ACK = new UInt8Field();
      public static final Field<Integer> FIELD_SEQUENCE = new UInt8Field().little();
      public static final Field<ByteBuffer> FIELD_RESERVED_2 = new ByteField(8);
      public static final Field<Integer> FIELD_PACKET_TYPE = new UInt16Field().little();
      public static final Field<ByteBuffer> FIELD_RESERVED_3 = new ByteField(2);
  
      /**
       * An ordered array of all fields contained in the common packet preamble.
       */
      public static final Field<?>[] PREAMBLE_FIELDS = new Field[] { FIELD_SIZE, FIELD_PROTOCOL, FIELD_SOURCE,
              FIELD_TARGET, FIELD_RESERVED_1, FIELD_ACK, FIELD_SEQUENCE, FIELD_RESERVED_2, FIELD_PACKET_TYPE,
              FIELD_RESERVED_3 };
  
      protected int size;
      protected int protocol;
      protected long source;
      protected MACAddress target;
      protected ByteBuffer reserved1;
      protected int ackbyte;
      protected int sequence;
      protected ByteBuffer reserved2;
      protected int packetType;
      protected ByteBuffer reserved3;
  
      protected long timeStamp;
  
      public int getSize() {
          return size;
      }
  
      public void setSize(int size) {
          this.size = size;
      }
  
      public int getOrigin() {
          return (protocol & 0xC000) >> 14;
      }
  
      public void setOrigin(int origin) {
          protocol = (protocol & ~(1 << 14)) | (origin << 14);
      }
  
      public boolean getTagged() {
          return (protocol & 0x2000) >> 13 == 1 ? true : false;
      }
  
      public void setTagged(boolean flag) {
          protocol = (protocol & ~(1 << 13)) | ((flag ? 1 : 0) << 13);
      }
  
      public boolean getAddressable() {
          return (protocol & 0x1000) >> 12 == 1 ? true : false;
      }
  
      public void setAddressable(boolean flag) {
          this.protocol = (protocol & ~(1 << 12)) | ((flag ? 1 : 0) << 12);
      }
  
      public int getProtocol() {
          return protocol & 0x0FFF;
      }
  
      public void setProtocol(int protocol) {
          this.protocol = this.protocol | protocol;
      }
  
      public long getSource() {
          return source;
      }
  
      public void setSource(long source) {
          this.source = source;
      }
  
      public MACAddress getTarget() {
          return target;
      }
  
      public void setTarget(MACAddress lightAddress) {
          this.target = lightAddress;
      }
  
      public ByteBuffer getReserved1() {
          return reserved1;
      }
  
      public void setReserved1(ByteBuffer reserved2) {
          this.reserved1 = reserved2;
      }
  
      public boolean getAckRequired() {
          return (ackbyte & 0x02) >> 1 == 1 ? true : false;
      }
  
      public void setAckRequired(boolean flag) {
          this.ackbyte = (ackbyte & ~(1 << 1)) | ((flag ? 1 : 0) << 1);
      }
  
      public boolean getResponseRequired() {
          return (ackbyte & 0x01) >> 0 == 1 ? true : false;
      }
  
      public void setResponseRequired(boolean flag) {
          this.ackbyte = (ackbyte & ~(1 << 0)) | ((flag ? 1 : 0) << 0);
      }
  
      public int getSequence() {
          return sequence;
      }
  
      public void setSequence(int sequence) {
          if (sequence < 255) {
              this.sequence = sequence;
          }
      }
  
      public ByteBuffer getReserved2() {
          return reserved2;
      }
  
      public void setReserved2(ByteBuffer reserved3) {
          this.reserved2 = reserved3;
      }
  
      public int getPacketType() {
          return packetType;
      }
  
      public void setPacketType(int packetType) {
          this.packetType = packetType;
      }
  
      public ByteBuffer getReserved3() {
          return reserved3;
      }
  
      public void setReserved3(ByteBuffer reserved4) {
          this.reserved3 = reserved4;
      }
  
      public long getTimeStamp() {
          return timeStamp;
      }
  
      /**
       * Creates an empty packet, setting some default values via
       * {@link #preambleDefaults()}.
       */
      public Packet() {
          preambleDefaults();
          timeStamp = System.currentTimeMillis();
      }
  
      /**
       * Parses, in order, the defined preamble fields, storing collected values.
       * The buffer's position will be left at the end of the parsed fields and
       * should be equal to the value returned by {@link #preambleLength()}.
       *
       * @param bytes the buffer to read from.
       */
      protected void parsePreamble(ByteBuffer bytes) {
          size = FIELD_SIZE.value(bytes);
          protocol = FIELD_PROTOCOL.value(bytes);
          source = FIELD_SOURCE.value(bytes);
          target = FIELD_TARGET.value(bytes);
          reserved1 = FIELD_RESERVED_1.value(bytes);
          ackbyte = FIELD_ACK.value(bytes);
          sequence = FIELD_SEQUENCE.value(bytes);
          reserved2 = FIELD_RESERVED_2.value(bytes);
          packetType = FIELD_PACKET_TYPE.value(bytes);
          reserved3 = FIELD_RESERVED_3.value(bytes);
      }
  
      /**
       * Calculates the length of the packet header, defined as the sum of the
       * lengths of all defined fields (see {@link #PREAMBLE_FIELDS}).
       *
       * @return the sum of the length of preamble fields
       */
      protected int preambleLength() {
          int sum = 0;
  
          for (Field<?> f : PREAMBLE_FIELDS) {
              sum += f.getLength();
          }
  
          return sum;
      }
  
      /**
       * Returns a new {@code ByteBuffer} containing the encoded preamble. Note
       * that the returned buffer will have its position set at the end of the
       * buffer and will need to have {@link ByteBuffer#rewind()} called before
       * use.
       *
       * <p>
       * The length of the buffer is the sum of the lengths of the defined
       * preamble fields (see {@link #PREAMBLE_FIELDS} for an ordered list), which
       * may also be accessed via {@link #preambleLength()}.
       *
       * <p>
       * Certain fields are set to default values based on other class methods.
       * For example, the size and packet type fields will be set to the values
       * returned from {@link #length()} and {@link #packetType()}, respectively.
       * Other defaults (such as the protocol, light address, site, and timestamp)
       * may be specified either by directly setting the relevant protected
       * variables or by overriding {@link #preambleDefaults()}.
       *
       * @return a new buffer containing the encoded preamble
       */
      protected ByteBuffer preambleBytes() {
          return ByteBuffer.allocate(preambleLength()).put(FIELD_SIZE.bytes(length())).put(FIELD_PROTOCOL.bytes(protocol))
                  .put(FIELD_SOURCE.bytes(source)).put(FIELD_TARGET.bytes(target))
                  .put(ByteBuffer.allocate(FIELD_RESERVED_1.getLength())) // empty
                  .put(FIELD_ACK.bytes(ackbyte)).put(FIELD_SEQUENCE.bytes(sequence))
                  .put(ByteBuffer.allocate(FIELD_RESERVED_2.getLength())) // empty
                  .put(FIELD_PACKET_TYPE.bytes(packetType())).put(ByteBuffer.allocate(FIELD_RESERVED_3.getLength())); // empty
      }
  
      /**
       * Sets default preamble values. If needed, subclasses may override these
       * values by specifically overriding this method, or by setting individual
       * values within the constructor, as this method is called automatically
       * during initialization.
       */
      protected void preambleDefaults() {
          size = 0;
          protocol = 1024;
          target = new MACAddress();
          sequence = 0;
          packetType = packetType();
      }
  
      /**
       * Returns the packet type. Note that this value is technically distinct
       * from {@code getPacketType()} in that it returns the packet type the
       * current {@code Packet} subtype is designed to parse, while
       * {@code getPacketType()} returns the actual {@code packetType} field of
       * a parsed packet. However, these values should always match.
       *
       * @return the packet type intended to be handled by this Packet subtype
       */
      public abstract int packetType();
  
      /**
       * Returns the length of the payload specific to this packet subtype. The
       * length of the preamble is specifically excluded.
       *
       * @return the length of this specialized packet payload
       */
      protected abstract int packetLength();
  
      /**
       * Parses the given {@link ByteBuffer} into class fields. Subtypes may
       * implement {@link #parsePacket(ByteBuffer)} to parse additional fields;
       * the preamble by default is always parsed.
       *
       * @param bytes the buffer to extract data from
       */
      public void parse(ByteBuffer bytes) {
          bytes.rewind();
          parsePreamble(bytes);
          parsePacket(bytes);
      }
  
      /**
       * Extracts data from the given {@link ByteBuffer} into fields specific to
       * this packet subtype. The preamble will already have been parsed; as such,
       * the buffer will be positioned at the end of the preamble. If needed,
       * {@link #preambleLength()} may be used to restore the position of the
       * buffer.
       *
       * @param bytes the raw bytes to parse
       */
      protected abstract void parsePacket(ByteBuffer bytes);
  
      /**
       * Returns a {@link ByteBuffer} containing the full payload for this packet,
       * including the populated preamble and any specialized packet payload. The
       * returned buffer will be at position zero.
       *
       * @return the full packet payload
       */
      public ByteBuffer bytes() {
          ByteBuffer preamble = preambleBytes();
          preamble.rewind();
  
          ByteBuffer packet = packetBytes();
          packet.rewind();
  
          ByteBuffer ret = ByteBuffer.allocate(length()).put(preamble).put(packet);
          ret.rewind();
  
          return ret;
      }
  
      /**
       * Returns a {@link ByteBuffer} containing the payload for this packet. Its
       * length must match the value of {@link #packetLength()}. This specifically
       * excludes preamble fields and should contain only data specific to the
       * packet subtype.
       * <p>
       * Note that returned ByteBuffers will have {@link ByteBuffer#rewind()}
       * called automatically before they are appended to the final packet
       * buffer.
       *
       * @return the packet payload
       */
      protected abstract ByteBuffer packetBytes();
  
      /**
       * Gets the total length of this packet, in bytes. Specifically, this method
       * is the sum of the preamble ({@link #preambleLength()}) and the payload
       * length ({@link #packetLength()}); subtypes should override methods for
       * those values if desired.
       *
       * @return the total length of this packet
       */
      public int length() {
          return preambleLength() + packetLength();
      }
  
      /**
       * Returns a list of expected response packet types. An empty array means
       * no responses are expected (suitable for response packet definitions),
       *
       * @return a list of expected responses
       */
      public abstract int[] expectedResponses();
  
      public boolean isExpectedResponse(int type) {
          for (int a : expectedResponses()) {
              if (a == type) {
                  return true;
              }
          }
  
          return false;
      }
  
      public boolean isFulfilled(Packet somePacket) {
  