/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jdo.tck.pc.singlefieldidentity;

import javax.jdo.identity.ByteIdentity;
import javax.jdo.identity.SingleFieldIdentity;

/**
 * The PC class for testing <code>ByteIdentity</code>.
 *
 * @author Michael Watzek
 */
public class PCPointSingleFieldByte extends AbstractPCPointSingleField {

  private static final long serialVersionUID = 1L;

  /**
   * Returns a unique value, used for primary key field initialization.
   *
   * @return a unique value
   */
  private static byte newId() {
    synchronized (PCPointSingleFieldByte.class) {
      return (byte) ((counter++) % Byte.MAX_VALUE);
    }
  }

  /** The primary key field. */
  private Byte id = Byte.valueOf(newId());

  public int x;
  public Integer y;

  /**
   * This constructor is used by test cases checking assertion A7.12-38:<br>
   * For classes using single field identity method <code>PersistenceCapable.newObjectIdInstance()
   * </code> must be called on a persistent instance with its primary key field initialized, or a
   * JDOFatalInternalException is thrown.
   */
  public PCPointSingleFieldByte() {
    this.id = null;
  }

  /**
   * This constructor is used by test cases checking assertion A7.12-39:<br>
   * The instance returned is initialized with the value of the primary key field of the instance on
   * which the method is called.
   *
   * @param x the x coordinate
   * @param y the y coordinate
   */
  public PCPointSingleFieldByte(int x, int y) {
    this.x = x;
    this.y = Integer.valueOf(y);
  }

  public void setX(int x) {
    this.x = x;
  }

  public int getX() {
    return x;
  }

  public void setY(Integer y) {
    this.y = y;
  }

  public Integer getY() {
    return y;
  }

  public String name() {
    return " x: " + getX() + ", y: " + getY().intValue();
  }

  /**
   * Returns <code>true</code> if the given the key of the given <code>SingleFieldIdentity</code>
   * instance equals the key in the subclass of this class.
   *
   * @param singleFieldIdentity the single field identity to check.
   * @return returns <code>true</code> if the given the key of the given <code>SingleFieldIdentity
   *     </code> instance equals the key in the subclass of this class.
   */
  public boolean equalsPKField(SingleFieldIdentity singleFieldIdentity) {
    return this.id.byteValue() == ((ByteIdentity) singleFieldIdentity).getKey();
  }

  public String toString() {
    return super.toString() + this.id;
  }
}
