/*
 * 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
<<<<<<< Updated upstream
 *
 *     http://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
=======
 * 
 *     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 
>>>>>>> Stashed changes
 * limitations under the License.
 */

package javax.jdo.pc;

import javax.jdo.PersistenceManager;
import javax.jdo.spi.JDOImplHelper;
import javax.jdo.spi.PersistenceCapable;
import javax.jdo.spi.StateManager;

/**
 * This is a hand-enhanced version of a simple class with two fields. The enhanced code assumes
 * datastore identity.
 *
 * @version 2.0
 */
public class PCPoint implements PersistenceCapable {
  public int x;
  public Integer y;

  // JDO generated fields
  protected transient StateManager jdoStateManager;
  protected transient byte jdoFlags;
  private static final int jdoInheritedFieldCount = 0;
  private static final String jdoFieldNames[] = {"x", "y"};
  private static final Class<?> jdoFieldTypes[];
  private static final byte jdoFieldFlags[] = {
    (byte)
        (PersistenceCapable.CHECK_READ
            + PersistenceCapable.CHECK_WRITE
            + PersistenceCapable.SERIALIZABLE),
    (byte)
        (PersistenceCapable.CHECK_READ
            + PersistenceCapable.CHECK_WRITE
            + PersistenceCapable.SERIALIZABLE),
  };
  private static final Class<?> jdoPersistenceCapableSuperclass;

  static {
    jdoFieldTypes = (new Class[] {Integer.TYPE, sunjdo$classForName$("java.lang.Integer")});
    jdoPersistenceCapableSuperclass = null;
    JDOImplHelper.registerClass(
        sunjdo$classForName$("javax.jdo.pc.PCPoint"),
        jdoFieldNames,
        jdoFieldTypes,
        jdoFieldFlags,
        jdoPersistenceCapableSuperclass,
        new PCPoint());
  }

  /** JDO required no-args constructor. */
  public PCPoint() {}

  /** Constructor. */
  public PCPoint(int x, Integer y) {
    jdoSetx(this, x);
    jdoSety(this, y);
  }

  /** */
  public void setX(int x) {
    jdoSetx(this, x);
  }

  /** */
  public int getX() {
    return jdoGetx(this);
  }

  /** */
  public void setY(Integer y) {
    jdoSety(this, y);
  }

  /** */
  public Integer getY() {
    return jdoGety(this);
  }

  /** */
  public boolean equals(Object o) {
    if (o == null || !(o instanceof PCPoint)) return false;
    PCPoint other = (PCPoint) o;
    if (jdoGetx(this) != jdoGetx(other)) return false;
    if (jdoGety(this) == null) return jdoGety(other) == null;
    if (jdoGety(other) == null) return jdoGety(this) == null;
    else return jdoGety(this).intValue() == jdoGety(other).intValue();
  }

  /** */
  public int hashCode() {
    int code = getX();
    if (getY() != null) {
      code += getY().intValue();
    }
    return code;
  }

  /** */
  public String toString() {
    return "PCPoint(x: " + getX() + ", y: " + getY() + ")";
  }

  // Generated methods in least-derived PersistenceCapable class

  public final boolean jdoIsPersistent() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.isPersistent(this);
    else return false;
  }

  public final boolean jdoIsTransactional() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.isTransactional(this);
    else return false;
  }

  public final boolean jdoIsNew() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.isNew(this);
    else return false;
  }

  public final boolean jdoIsDirty() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.isDirty(this);
    else return false;
  }

  public final boolean jdoIsDeleted() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.isDeleted(this);
    else return false;
  }

  public final boolean jdoIsDetached() {
    return false;
  }

  public final void jdoMakeDirty(String s) {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) statemanager.makeDirty(this, s);
  }

  public final PersistenceManager jdoGetPersistenceManager() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.getPersistenceManager(this);
    else return null;
  }

  public final Object jdoGetObjectId() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.getObjectId(this);
    else return null;
  }

  public final Object jdoGetTransactionalObjectId() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.getTransactionalObjectId(this);
    else return null;
  }

  public final Object jdoGetVersion() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) return statemanager.getVersion(this);
    else return null;
  }

  public final synchronized void jdoReplaceStateManager(StateManager statemanager) {
    StateManager statemanager1 = jdoStateManager;
    if (statemanager1 != null) {
      jdoStateManager = statemanager1.replacingStateManager(this, statemanager);
      return;
    } else {
      JDOImplHelper.checkAuthorizedStateManager(statemanager);
      jdoStateManager = statemanager;
      jdoFlags = PersistenceCapable.LOAD_REQUIRED;
      return;
    }
  }

  public final void jdoReplaceFlags() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) jdoFlags = statemanager.replacingFlags(this);
  }

  public final void jdoReplaceFields(int fields[]) {
    if (fields == null) throw new IllegalArgumentException("fields is null");
    int i = fields.length;
    for (int j = 0; j < i; j++) jdoReplaceField(fields[j]);
  }

  public final void jdoProvideFields(int fields[]) {
    if (fields == null) throw new IllegalArgumentException("fields is null");
    int i = fields.length;
    for (int j = 0; j < i; j++) jdoProvideField(fields[j]);
  }

  protected final void jdoPreSerialize() {
    StateManager statemanager = jdoStateManager;
    if (statemanager != null) statemanager.preSerialize(this);
  }

  // Generated methods in PersistenceCapable root classes and all classes
  // that declare objectid-class in xml metadata:

  public void jdoCopyKeyFieldsToObjectId(
      PersistenceCapable.ObjectIdFieldSupplier objectidfieldsupplier, Object obj) {}

  public void jdoCopyKeyFieldsToObjectId(Object obj) {}

  public void jdoCopyKeyFieldsFromObjectId(
      PersistenceCapable.ObjectIdFieldConsumer objectidfieldconsumer, Object obj) {}

  protected void jdoCopyKeyFieldsFromObjectId(Object obj) {}

  public Object jdoNewObjectIdInstance() {
    return null;
  }

  public Object jdoNewObjectIdInstance(Object o) {
    return null;
  }

  // Generated methods in all PersistenceCapable classes

  public PersistenceCapable jdoNewInstance(StateManager statemanager) {
    PCPoint pcpoint = new PCPoint();
    pcpoint.jdoFlags = PersistenceCapable.LOAD_REQUIRED;
    pcpoint.jdoStateManager = statemanager;
    return pcpoint;
  }

  public PersistenceCapable jdoNewInstance(StateManager statemanager, Object obj) {
    PCPoint pcpoint = new PCPoint();
    pcpoint.jdoCopyKeyFieldsFromObjectId(obj);
    pcpoint.jdoFlags = PersistenceCapable.LOAD_REQUIRED;
    pcpoint.jdoStateManager = statemanager;
    return pcpoint;
  }

  protected static int jdoGetManagedFieldCount() {
    return 2;
  }

  public static int jdoGetx(PCPoint pcpoint) {
    if (pcpoint.jdoFlags <= PersistenceCapable.READ_WRITE_OK) return pcpoint.x;
    StateManager statemanager = pcpoint.jdoStateManager;
    if (statemanager == null) return pcpoint.x;
    if (statemanager.isLoaded(pcpoint, jdoInheritedFieldCount + 0)) return pcpoint.x;
    else return statemanager.getIntField(pcpoint, jdoInheritedFieldCount + 0, pcpoint.x);
  }

  public static Integer jdoGety(PCPoint pcpoint) {
    if (pcpoint.jdoFlags <= PersistenceCapable.READ_WRITE_OK) return pcpoint.y;
    StateManager statemanager = pcpoint.jdoStateManager;
    if (statemanager == null) return pcpoint.y;
    if (statemanager.isLoaded(pcpoint, jdoInheritedFieldCount + 1)) return pcpoint.y;
    else
      return (Integer) statemanager.getObjectField(pcpoint, jdoInheritedFieldCount + 1, pcpoint.y);
  }

  public static void jdoSetx(PCPoint pcpoint, int i) {
    if (pcpoint.jdoFlags == PersistenceCapable.READ_WRITE_OK) {
      pcpoint.x = i;
      return;
    }
    StateManager statemanager = pcpoint.jdoStateManager;
    if (statemanager == null) {
      pcpoint.x = i;
      return;
    } else {
      statemanager.setIntField(pcpoint, jdoInheritedFieldCount + 0, pcpoint.x, i);
      return;
    }
  }

  public static void jdoSety(PCPoint pcpoint, Integer integer) {
    if (pcpoint.jdoFlags == PersistenceCapable.READ_WRITE_OK) {
      pcpoint.y = integer;
      return;
    }
    StateManager statemanager = pcpoint.jdoStateManager;
    if (statemanager == null) {
      pcpoint.y = integer;
      return;
    } else {
      statemanager.setObjectField(pcpoint, jdoInheritedFieldCount + 1, pcpoint.y, integer);
      return;
    }
  }

  public void jdoReplaceField(int field) {
    StateManager statemanager = jdoStateManager;
    switch (field - jdoInheritedFieldCount) {
      case 0:
        if (statemanager == null) {
          throw new IllegalStateException("jdoStateManager is null");
        } else {
          x = statemanager.replacingIntField(this, field);
          return;
        }
      case 1:
        if (statemanager == null) {
          throw new IllegalStateException("jdoStateManager is null");
        } else {
          y = (Integer) statemanager.replacingObjectField(this, field);
          return;
        }
    }
    throw new IllegalArgumentException("field number out of range");
  }

  public void jdoProvideField(int field) {
    StateManager statemanager = jdoStateManager;
    switch (field - jdoInheritedFieldCount) {
      case 0:
        if (statemanager == null) {
          throw new IllegalStateException("jdoStateManager is null");
        } else {
          statemanager.providedIntField(this, field, x);
          return;
        }
      case 1:
        if (statemanager == null) {
          throw new IllegalStateException("jdoStateManager is null");
        } else {
          statemanager.providedObjectField(this, field, y);
          return;
        }
    }
    throw new IllegalArgumentException("field number out of range");
  }

  public void jdoCopyFields(Object obj, int fieldNumbers[]) {
    if (jdoStateManager == null) throw new IllegalStateException("jdoStateManager is null");
    if (!(obj instanceof PCPoint)) throw new ClassCastException(obj.getClass().getName());
    if (fieldNumbers == null) throw new IllegalArgumentException("fieldNumber is null");
    PCPoint pcpoint = (PCPoint) obj;
    if (pcpoint.jdoStateManager != jdoStateManager)
      throw new IllegalArgumentException("wrong jdoStateManager");
    int i = fieldNumbers.length;
    for (int j = 0; j < i; j++) jdoCopyField(pcpoint, fieldNumbers[j]);
  }

  protected final void jdoCopyField(PCPoint pcpoint, int fieldNumber) {
    switch (fieldNumber - jdoInheritedFieldCount) {
      case 0:
        if (pcpoint == null) {
          throw new IllegalArgumentException("pcpoint is null");
        } else {
          x = pcpoint.x;
          return;
        }
      case 1:
        if (pcpoint == null) {
          throw new IllegalArgumentException("pcpoint is null");
        } else {
          y = pcpoint.y;
          return;
        }
    }
    throw new IllegalArgumentException("field number out of range");
  }

  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
    jdoPreSerialize();
    out.defaultWriteObject();
  }

  protected static Class<?> sunjdo$classForName$(String s) {
    try {
      return Class.forName(s);
    } catch (ClassNotFoundException ex) {
      throw new NoClassDefFoundError(ex.getMessage());
    }
  }
}
