All Downloads are FREE. Search and download functionalities are using the official Maven repository.

enterprises.orbital.evekit.model.character.sync.CharacterPlanetaryColoniesSync Maven / Gradle / Ivy

package enterprises.orbital.evekit.model.character.sync;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;

import enterprises.orbital.evekit.account.SynchronizedEveAccount;
import enterprises.orbital.evekit.model.CachedData;
import enterprises.orbital.evekit.model.CapsuleerSyncTracker;
import enterprises.orbital.evekit.model.ModelUtil;
import enterprises.orbital.evekit.model.SyncTracker;
import enterprises.orbital.evekit.model.SyncTracker.SyncState;
import enterprises.orbital.evekit.model.SynchronizerUtil;
import enterprises.orbital.evekit.model.SynchronizerUtil.SyncStatus;
import enterprises.orbital.evekit.model.character.Capsuleer;
import enterprises.orbital.evekit.model.character.PlanetaryColony;
import enterprises.orbital.evekit.model.character.PlanetaryLink;
import enterprises.orbital.evekit.model.character.PlanetaryPin;
import enterprises.orbital.evekit.model.character.PlanetaryRoute;
import enterprises.orbital.evexmlapi.chr.ICharacterAPI;
import enterprises.orbital.evexmlapi.chr.IPlanetaryColony;
import enterprises.orbital.evexmlapi.chr.IPlanetaryLink;
import enterprises.orbital.evexmlapi.chr.IPlanetaryPin;
import enterprises.orbital.evexmlapi.chr.IPlanetaryRoute;

public class CharacterPlanetaryColoniesSync extends AbstractCharacterSync {
  protected static final Logger log = Logger.getLogger(CharacterPlanetaryColoniesSync.class.getName());

  @Override
  public boolean isRefreshed(
                             CapsuleerSyncTracker tracker) {
    return tracker.getPlanetaryColoniesStatus() != SyncTracker.SyncState.NOT_PROCESSED;
  }

  @Override
  public void updateStatus(
                           CapsuleerSyncTracker tracker,
                           SyncState status,
                           String detail) {
    tracker.setPlanetaryColoniesStatus(status);
    tracker.setPlanetaryColoniesDetail(detail);
    CapsuleerSyncTracker.updateTracker(tracker);
  }

  @Override
  public void updateExpiry(
                           Capsuleer container,
                           long expiry) {
    container.setPlanetaryColoniesExpiry(expiry);
    CachedData.updateData(container);
  }

  @Override
  public long getExpiryTime(
                            Capsuleer container) {
    return container.getPlanetaryColoniesExpiry();
  }

  @Override
  public boolean commit(
                        long time,
                        CapsuleerSyncTracker tracker,
                        Capsuleer container,
                        SynchronizedEveAccount accountKey,
                        CachedData item) {
    // Handle the four types of planetary info
    if (item instanceof PlanetaryColony) {
      PlanetaryColony api = (PlanetaryColony) item;

      if (api.getLifeStart() != 0) {
        // Special case. This is an existing PlanetaryColony to be EOL
        super.commit(time, tracker, container, accountKey, api);
      } else {
        PlanetaryColony existing = PlanetaryColony.get(accountKey, time, api.getPlanetID());
        if (existing != null) {
          if (!existing.equivalent(api)) {
            // Evolve
            existing.evolve(api, time);
            super.commit(time, tracker, container, accountKey, existing);
            super.commit(time, tracker, container, accountKey, api);
          }
        } else {
          // New entity
          api.setup(accountKey, time);
          super.commit(time, tracker, container, accountKey, api);
        }
      }
    } else if (item instanceof PlanetaryLink) {
      PlanetaryLink api = (PlanetaryLink) item;

      if (api.getLifeStart() != 0) {
        // Special case. This is an existing PlanetaryLink to be EOL
        super.commit(time, tracker, container, accountKey, api);
      } else {
        PlanetaryLink existing = PlanetaryLink.get(accountKey, time, api.getPlanetID(), api.getSourcePinID(), api.getDestinationPinID());
        if (existing != null) {
          if (!existing.equivalent(api)) {
            // Evolve
            existing.evolve(api, time);
            super.commit(time, tracker, container, accountKey, existing);
            super.commit(time, tracker, container, accountKey, api);
          }
        } else {
          // New entity
          api.setup(accountKey, time);
          super.commit(time, tracker, container, accountKey, api);
        }
      }
    } else if (item instanceof PlanetaryPin) {
      PlanetaryPin api = (PlanetaryPin) item;

      if (api.getLifeStart() != 0) {
        // Special case. This is an existing PlanetaryPin to be EOL
        super.commit(time, tracker, container, accountKey, api);
      } else {
        PlanetaryPin existing = PlanetaryPin.get(accountKey, time, api.getPlanetID(), api.getPinID(), api.getContentTypeID());
        if (existing != null) {
          if (!existing.equivalent(api)) {
            // Evolve
            existing.evolve(api, time);
            super.commit(time, tracker, container, accountKey, existing);
            super.commit(time, tracker, container, accountKey, api);
          }
        } else {
          // New entity
          api.setup(accountKey, time);
          super.commit(time, tracker, container, accountKey, api);
        }
      }
    } else if (item instanceof PlanetaryRoute) {
      PlanetaryRoute api = (PlanetaryRoute) item;

      if (api.getLifeStart() != 0) {
        // Special case. This is an existing PlanetaryRoute to be EOL
        super.commit(time, tracker, container, accountKey, api);
      } else {
        PlanetaryRoute existing = PlanetaryRoute.get(accountKey, time, api.getPlanetID(), api.getRouteID());
        if (existing != null) {
          if (!existing.equivalent(api)) {
            // Evolve
            existing.evolve(api, time);
            super.commit(time, tracker, container, accountKey, existing);
            super.commit(time, tracker, container, accountKey, api);
          }
        } else {
          // New entity
          api.setup(accountKey, time);
          super.commit(time, tracker, container, accountKey, api);
        }
      }
    } else {
      assert false;
    }

    return true;
  }

  // Can't use generic sync for planetary data
  @Override
  protected Object getServerData(
                                 ICharacterAPI charRequest) throws IOException {
    throw new UnsupportedOperationException();
  }

  @Override
  protected long processServerData(
                                   long time,
                                   SynchronizedEveAccount syncAccount,
                                   ICharacterAPI charRequest,
                                   Object data,
                                   List updates) throws IOException {
    throw new UnsupportedOperationException();
  }

  private static final CharacterPlanetaryColoniesSync syncher = new CharacterPlanetaryColoniesSync();

  private static class NaryKey {
    long[] keys;

    public NaryKey(long... k) {
      keys = new long[k.length];
      System.arraycopy(k, 0, keys, 0, k.length);
    }

    @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + Arrays.hashCode(keys);
      return result;
    }

    @Override
    public boolean equals(
                          Object obj) {
      if (this == obj) return true;
      if (obj == null) return false;
      if (getClass() != obj.getClass()) return false;
      NaryKey other = (NaryKey) obj;
      if (!Arrays.equals(keys, other.keys)) return false;
      return true;
    }
  }

  public static SyncStatus syncPlanetaryColonies(
                                                 long time,
                                                 SynchronizedEveAccount syncAccount,
                                                 SynchronizerUtil syncUtil,
                                                 ICharacterAPI charRequest) {
    try {
      // Run pre-check.
      String description = "PlanetaryColonies";
      SyncStatus preCheck = syncUtil.preSyncCheck(CapsuleerSyncTracker.class, Capsuleer.class, syncAccount, description, syncher);
      if (preCheck != SyncStatus.CONTINUE) return preCheck;

      // Start server sync
      log.fine("Starting refresh request for " + description + "  for account " + syncAccount);

      SyncTracker.SyncState status = SyncTracker.SyncState.UPDATED;
      String errorDetail = null;
      long nextExpiry = -1;
      List updateList = new ArrayList();

      try {
        // Load planetary colonies and all related pins, links and routes.
        // Schedule missing colonies, pins, links and routes for deletion.
        long minRefreshTime = Long.MAX_VALUE;
        Collection colonies = charRequest.requestPlanetaryColonies();
        minRefreshTime = Math.min(ModelUtil.safeConvertDate(charRequest.getCachedUntil()), minRefreshTime);
        if (charRequest.isError()) {
          // erroneous loop termination
          StringBuilder errStr = new StringBuilder();
          status = handleServerError(charRequest, errStr);
          errorDetail = errStr.toString();
          if (status == SyncTracker.SyncState.SYNC_ERROR) log.warning("request failed: " + errorDetail);
        }

        get_colonies: while (status == SyncTracker.SyncState.UPDATED) {
          Map> linkSet = new HashMap>();
          Map> pinSet = new HashMap>();
          Map> routeSet = new HashMap>();

          // Collect all pins, links and routes for each colony.
          for (IPlanetaryColony next : colonies) {
            long pid = next.getPlanetID();
            linkSet.put(pid, charRequest.requestPlanetaryLinks(pid));
            if (charRequest.isError()) break;
            minRefreshTime = Math.min(ModelUtil.safeConvertDate(charRequest.getCachedUntil()), minRefreshTime);
            routeSet.put(pid, charRequest.requestPlanetaryRoutes(pid));
            if (charRequest.isError()) break;
            minRefreshTime = Math.min(ModelUtil.safeConvertDate(charRequest.getCachedUntil()), minRefreshTime);
            pinSet.put(pid, charRequest.requestPlanetaryPins(pid));
            if (charRequest.isError()) break;
            minRefreshTime = Math.min(ModelUtil.safeConvertDate(charRequest.getCachedUntil()), minRefreshTime);
          }

          if (charRequest.isError()) {
            // erroneous loop termination
            StringBuilder errStr = new StringBuilder();
            status = handleServerError(charRequest, errStr);
            errorDetail = errStr.toString();
            if (status != SyncTracker.SyncState.UPDATED) {
              log.warning("request exiting: " + errorDetail);
              break get_colonies;
            }
          }

          // Prepare colonies for population, EOL colonies which no longer exist.
          Set usedPD = new HashSet();
          for (IPlanetaryColony nextColony : colonies) {
            PlanetaryColony newC = new PlanetaryColony(
                nextColony.getPlanetID(), nextColony.getSolarSystemID(), nextColony.getSolarSystemName(), nextColony.getPlanetName(),
                nextColony.getPlanetTypeID(), nextColony.getPlanetTypeName(), nextColony.getOwnerID(), nextColony.getOwnerName(),
                ModelUtil.safeConvertDate(nextColony.getLastUpdate()), nextColony.getUpgradeLevel(), nextColony.getNumberOfPins());
            usedPD.add(new NaryKey(nextColony.getPlanetID()));
            updateList.add(newC);
          }
          for (PlanetaryColony check : PlanetaryColony.getAllPlanetaryColonies(syncAccount, time)) {
            if (!usedPD.contains(new NaryKey(check.getPlanetID()))) {
              check.evolve(null, time);
              updateList.add(check);
            }
          }

          // Prepare pins for population, EOL pins which no longer exist.
          usedPD.clear();
          for (Entry> nextPinMap : pinSet.entrySet()) {
            long pid = nextPinMap.getKey();
            for (IPlanetaryPin nextPin : nextPinMap.getValue()) {
              PlanetaryPin newP = new PlanetaryPin(
                  pid, nextPin.getPinID(), nextPin.getTypeID(), nextPin.getTypeName(), nextPin.getSchematicID(),
                  ModelUtil.safeConvertDate(nextPin.getLastLaunchTime()), nextPin.getCycleTime(), nextPin.getQuantityPerCycle(),
                  ModelUtil.safeConvertDate(nextPin.getInstallTime()), ModelUtil.safeConvertDate(nextPin.getExpiryTime()), nextPin.getContentTypeID(),
                  nextPin.getContentTypeName(), nextPin.getContentQuantity(), nextPin.getLongitude(), nextPin.getLatitude());
              usedPD.add(new NaryKey(pid, newP.getPinID(), newP.getContentTypeID()));
              updateList.add(newP);
            }
          }
          for (PlanetaryPin check : PlanetaryPin.getAllPlanetaryPins(syncAccount, time)) {
            long planetID = check.getPlanetID();
            long pinID = check.getPinID();
            int contentTypeID = check.getContentTypeID();
            if (!usedPD.contains(new NaryKey(planetID, pinID, contentTypeID))) {
              check.evolve(null, time);
              updateList.add(check);
            }
          }

          // Prepare links for population, EOL links which no longer exist.
          usedPD.clear();
          for (Entry> nextLinkMap : linkSet.entrySet()) {
            long pid = nextLinkMap.getKey();
            for (IPlanetaryLink nextLink : nextLinkMap.getValue()) {
              PlanetaryLink newP = new PlanetaryLink(pid, nextLink.getSourcePinID(), nextLink.getDestinationPinID(), nextLink.getLinkLevel());
              usedPD.add(new NaryKey(pid, newP.getSourcePinID(), newP.getDestinationPinID()));
              updateList.add(newP);
            }
          }
          for (PlanetaryLink check : PlanetaryLink.getAllPlanetaryLinks(syncAccount, time)) {
            long planetID = check.getPlanetID();
            long sourcePinID = check.getSourcePinID();
            long destPinID = check.getDestinationPinID();
            if (!usedPD.contains(new NaryKey(planetID, sourcePinID, destPinID))) {
              check.evolve(null, time);
              updateList.add(check);
            }
          }

          // Prepare routes for population, EOL routes which no longer exist.
          usedPD.clear();
          for (Entry> nextRouteMap : routeSet.entrySet()) {
            long pid = nextRouteMap.getKey();
            for (IPlanetaryRoute nextRoute : nextRouteMap.getValue()) {
              PlanetaryRoute newP = new PlanetaryRoute(
                  pid, nextRoute.getRouteID(), nextRoute.getSourcePinID(), nextRoute.getDestinationPinID(), nextRoute.getContentTypeID(),
                  nextRoute.getContentTypeName(), nextRoute.getQuantity(), nextRoute.getWaypoint1(), nextRoute.getWaypoint2(), nextRoute.getWaypoint3(),
                  nextRoute.getWaypoint4(), nextRoute.getWaypoint5());
              usedPD.add(new NaryKey(pid, newP.getRouteID()));
              updateList.add(newP);
            }
          }
          for (PlanetaryRoute check : PlanetaryRoute.getAllPlanetaryRoutes(syncAccount, time)) {
            long planetID = check.getPlanetID();
            long routeID = check.getRouteID();
            if (!usedPD.contains(new NaryKey(planetID, routeID))) {
              check.evolve(null, time);
              updateList.add(check);
            }
          }

          nextExpiry = minRefreshTime;
          break get_colonies;
        }

      } catch (IOException e) {
        status = SyncTracker.SyncState.SYNC_ERROR;
        errorDetail = "request failed with IO error";
        log.warning("request failed with error " + e);
      }

      log.fine("Completed refresh request for " + description + " for account " + syncAccount);

      syncUtil.storeSynchResults(time, CapsuleerSyncTracker.class, Capsuleer.class, syncAccount, status, errorDetail, nextExpiry, description, updateList,
                                 syncher);
      return SyncStatus.DONE;

    } catch (IOException e) {
      // Log but give us another shot in the queue
      log.warning("store failed with error " + e);
      return SyncStatus.ERROR;
    }
  }

  public static SyncStatus exclude(
                                   SynchronizedEveAccount syncAccount,
                                   SynchronizerUtil syncUtil) {
    return syncher.excludeState(syncAccount, syncUtil, "PlanetaryColonies", SyncTracker.SyncState.SYNC_ERROR);
  }

  public static SyncStatus notAllowed(
                                      SynchronizedEveAccount syncAccount,
                                      SynchronizerUtil syncUtil) {
    return syncher.excludeState(syncAccount, syncUtil, "PlanetaryColonies", SyncTracker.SyncState.NOT_ALLOWED);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy