/**
   * @param projectId
   * @param changePackage
   * @param projectHistory
   * @param newVersion
   * @param newProjectState
   * @throws FatalESException
   */
  private void trySave(
      ProjectId projectId,
      AbstractChangePackage changePackage,
      final ProjectHistory projectHistory,
      Version newVersion,
      final Project newProjectState)
      throws FatalESException {
    getResourceHelper()
        .createResourceForProject(
            newProjectState, newVersion.getPrimarySpec(), projectHistory.getProjectId());
    getResourceHelper()
        .createResourceForChangePackage(changePackage, newVersion.getPrimarySpec(), projectId);
    if (FileBasedChangePackage.class.isInstance(changePackage)) {
      try {
        /* move the temporary file to the project folder */
        final URI uri = changePackage.eResource().getURI();
        final URI normalizedUri =
            changePackage.eResource().getResourceSet().getURIConverter().normalize(uri);
        final String filePath = normalizedUri.toFileString() + ".1"; // $NON-NLS-1$
        FileBasedChangePackage.class.cast(changePackage).move(filePath);
        ModelUtil.saveResource(changePackage.eResource(), ModelUtil.getResourceLogger());
      } catch (final IOException ex) {
        throw new FatalESException(StorageException.NOSAVE, ex);
      }
    }

    getResourceHelper().createResourceForVersion(newVersion, projectHistory.getProjectId());

    newVersion.setProjectStateResource(newProjectState.eResource());
    newVersion.setChangeResource(changePackage.eResource());
  }
  private PrimaryVersionSpec resolvePrimaryVersionSpec(
      ProjectHistory projectHistory, PrimaryVersionSpec versionSpec)
      throws InvalidVersionSpecException {
    final int index = versionSpec.getIdentifier();
    final String branch = versionSpec.getBranch();
    final int versions = projectHistory.getVersions().size();
    if (0 > index || index >= versions || branch == null) {
      throw new InvalidVersionSpecException(
          MessageFormat.format(Messages.VersionSubInterfaceImpl_InvalidVersionRequested, index));
    }

    if (branch.equals(VersionSpec.GLOBAL)) {
      return projectHistory.getVersions().get(index).getPrimarySpec();
    }

    // Get biggest primary version of given branch which is equal or lower
    // to the given versionSpec
    for (int i = index; i >= 0; i--) {
      final Version version = projectHistory.getVersions().get(i);
      if (branch.equals(version.getPrimarySpec().getBranch())) {
        return version.getPrimarySpec();
      }
    }
    throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_PrimaryVersionNotFound);
  }
 private Version getVersion(ProjectHistory projectHistory, PrimaryVersionSpec baseVersionSpec) {
   if (0 > baseVersionSpec.getIdentifier()
       || baseVersionSpec.getIdentifier() > projectHistory.getVersions().size() - 1) {
     return null;
   }
   final Version version = projectHistory.getVersions().get(baseVersionSpec.getIdentifier());
   if (version == null || !version.getPrimarySpec().equals(baseVersionSpec)) {
     return null;
   }
   return version;
 }
 /**
  * Returns all branches for the project with the given ID.
  *
  * @param projectId the ID of a project
  * @return a list containing information about each branch
  * @throws ESException in case of failure
  */
 @ESMethod(MethodId.GETBRANCHES)
 public List<BranchInfo> getBranches(ProjectId projectId) throws ESException {
   synchronized (getMonitor()) {
     final ProjectHistory projectHistory =
         getSubInterface(ProjectSubInterfaceImpl.class).getProject(projectId);
     final ArrayList<BranchInfo> result = new ArrayList<BranchInfo>();
     for (final BranchInfo branch : projectHistory.getBranches()) {
       result.add(ModelUtil.clone(branch));
     }
     return result;
   }
 }
 private PrimaryVersionSpec resolveHeadVersionSpec(
     ProjectHistory projectHistory, HeadVersionSpec versionSpec)
     throws InvalidVersionSpecException {
   if (VersionSpec.GLOBAL.equals(versionSpec.getBranch())) {
     return projectHistory
         .getVersions()
         .get(projectHistory.getVersions().size() - 1)
         .getPrimarySpec();
   }
   final BranchInfo info = getBranchInfo(projectHistory, versionSpec);
   if (info != null) {
     return info.getHead();
   }
   throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_HeadVersionNotFound);
 }
 private BranchInfo getBranchInfo(ProjectHistory projectHistory, VersionSpec versionSpec) {
   for (final BranchInfo branchInfo : projectHistory.getBranches()) {
     if (branchInfo.getName().equals(versionSpec.getBranch())) {
       return branchInfo;
     }
   }
   return null;
 }
 private PrimaryVersionSpec resolveDateVersionSpec(
     ProjectHistory projectHistory, DateVersionSpec versionSpec) {
   for (final Version version : projectHistory.getVersions()) {
     final LogMessage logMessage = version.getLogMessage();
     if (logMessage == null || logMessage.getDate() == null) {
       continue;
     }
     if (versionSpec.getDate().before(logMessage.getDate())) {
       final Version previousVersion = version.getPreviousVersion();
       if (previousVersion == null) {
         return VersioningFactory.eINSTANCE.createPrimaryVersionSpec();
       }
       return previousVersion.getPrimarySpec();
     }
   }
   return projectHistory.getLastVersion().getPrimarySpec();
 }
  private Version createVersion(
      ProjectHistory projectHistory,
      Project projectState,
      LogMessage logMessage,
      ACUser user,
      Version previousVersion)
      throws ESException {
    final Version newVersion = VersioningFactory.eINSTANCE.createVersion();

    long computedChecksum = ModelUtil.NO_CHECKSUM;

    try {
      if (ServerConfiguration.isComputeChecksumOnCommitActive()) {
        computedChecksum = ModelUtil.computeChecksum(projectState);
      }
    } catch (final SerializationException exception) {
      // TODO: clarify what to do in case checksum computation fails + provide ext. point
      throw new ESException(
          MessageFormat.format(
              Messages.VersionSubInterfaceImpl_ChecksumComputationFailed,
              projectHistory.getProjectName()),
          exception);
    }

    // newVersion.setChanges(changePackage);

    logMessage.setDate(new Date());
    logMessage.setAuthor(user.getName());
    newVersion.setLogMessage(logMessage);

    // latest version == getVersion.size() (version start with index 0 as
    // the list), branch from previous is used.
    newVersion.setPrimarySpec(
        Versions.createPRIMARY(
            previousVersion.getPrimarySpec(), projectHistory.getVersions().size()));
    newVersion.getPrimarySpec().setProjectStateChecksum(computedChecksum);
    newVersion.setNextVersion(null);

    projectHistory.getVersions().add(newVersion);
    return newVersion;
  }
 private PrimaryVersionSpec resolveTagVersionSpec(
     ProjectHistory projectHistory, TagVersionSpec versionSpec)
     throws InvalidVersionSpecException {
   for (final Version version : projectHistory.getVersions()) {
     for (final TagVersionSpec tag : version.getTagSpecs()) {
       if (versionSpec.equals(tag)) {
         return ModelUtil.clone(version.getPrimarySpec());
       }
     }
   }
   throw new InvalidVersionSpecException(Messages.VersionSubInterfaceImpl_TagVersionNotFound);
 }
  private void rollback(
      final ProjectHistory projectHistory,
      final BranchInfo baseBranch,
      final Version baseVersion,
      Version newVersion,
      BranchInfo newBranch,
      final FatalESException e)
      throws StorageException {
    projectHistory.getVersions().remove(newVersion);

    if (newBranch == null) {
      // normal commit
      baseVersion.setNextVersion(null);
      baseBranch.setHead(ModelUtil.clone(baseVersion.getPrimarySpec()));
    } else {
      // branch commit
      baseVersion.getBranchedVersions().remove(newVersion);
      projectHistory.getBranches().remove(newBranch);
    }
    // TODO: delete obsolete project, change package and version files
    throw new StorageException(StorageException.NOSAVE, e);
  }
  private BranchInfo createNewBranch(
      ProjectHistory projectHistory,
      PrimaryVersionSpec baseSpec,
      PrimaryVersionSpec primarySpec,
      BranchVersionSpec branch) {
    primarySpec.setBranch(branch.getBranch());

    final BranchInfo branchInfo = VersioningFactory.eINSTANCE.createBranchInfo();
    branchInfo.setName(branch.getBranch());
    branchInfo.setSource(ModelUtil.clone(baseSpec));
    branchInfo.setHead(ModelUtil.clone(primarySpec));

    projectHistory.getBranches().add(branchInfo);

    return branchInfo;
  }
  private PrimaryVersionSpec resolvePagedUpdateVersionSpec(
      ProjectHistory projectHistory, PagedUpdateVersionSpec baseVersion) {

    int changes = 0;
    PrimaryVersionSpec resolvedSpec = baseVersion.getBaseVersionSpec();
    int maxChanges = baseVersion.getMaxChanges();

    int i = resolvedSpec.getIdentifier();

    AbstractChangePackage cp = projectHistory.getVersions().get(i).getChanges();

    if (i == projectHistory.getVersions().size() - 1) {
      return projectHistory.getVersions().get(i).getPrimarySpec();
    }

    do {
      cp = projectHistory.getVersions().get(++i).getChanges();
    } while (cp == null && i < projectHistory.getVersions().size());

    // pull at least one change package
    if (cp.leafSize() > maxChanges) {
      maxChanges = cp.leafSize();
    }

    while (changes < maxChanges && i < projectHistory.getVersions().size()) {
      resolvedSpec = projectHistory.getVersions().get(i).getPrimarySpec();
      final Version version = projectHistory.getVersions().get(i);
      final AbstractChangePackage changePackage = version.getChanges();

      if (changePackage != null) {
        final int size = changePackage.leafSize();
        if (changes + size >= maxChanges) {
          resolvedSpec = projectHistory.getVersions().get(i).getPrimarySpec();
          break;
        }
        changes += size;
      }
      i += 1;
    }

    return resolvedSpec;
  }