/**
  * Factory method for path query. Getting all changes from source to target.
  *
  * @param source source version
  * @param target target version
  * @param allVersions include all versions, from all branches
  * @param includeCp include changepackages
  * @return query
  */
 public static PathQuery pathQuery(
     PrimaryVersionSpec source,
     PrimaryVersionSpec target,
     boolean allVersions,
     boolean includeCp) {
   final PathQuery query = VersioningFactory.eINSTANCE.createPathQuery();
   query.setSource(ModelUtil.clone(source));
   query.setTarget(ModelUtil.clone(target));
   query.setIncludeAllVersions(allVersions);
   query.setIncludeChangePackages(includeCp);
   return query;
 }
  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;
  }
 /**
  * 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 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);
 }
 /**
  * Factory method for modelelements range queries.
  *
  * @param source source version
  * @param modelElements modelelements
  * @param upper upper limit
  * @param lower lower limit
  * @param allVersions include all versions, from all branches
  * @param includeCp include change packages
  * @return query
  */
 public static ModelElementQuery modelelementQuery(
     PrimaryVersionSpec source,
     List<ModelElementId> modelElements,
     int upper,
     int lower,
     boolean allVersions,
     boolean includeCp) {
   final ModelElementQuery query = VersioningFactory.eINSTANCE.createModelElementQuery();
   query.setSource(ModelUtil.clone(source));
   query.getModelElements().addAll(modelElements);
   query.setUpperLimit(upper);
   query.setLowerLimit(lower);
   query.setIncludeAllVersions(allVersions);
   query.setIncludeChangePackages(includeCp);
   query.setIncludeIncoming(false);
   query.setIncludeOutgoing(false);
   return query;
 }
 /**
  * Factory method for range query.
  *
  * @param source source version
  * @param upper upper limit
  * @param lower lower limit
  * @param allVersions include all versions, from all branches
  * @param incoming include incoming versions, only if allVersions is false
  * @param outgoing include outgoing versions
  * @param includeCp include changepackges
  * @return query
  */
 public static RangeQuery<?> rangeQuery(
     PrimaryVersionSpec source,
     int upper,
     int lower,
     boolean allVersions,
     boolean incoming,
     boolean outgoing,
     boolean includeCp) {
   final RangeQuery<?> query = VersioningFactory.eINSTANCE.createRangeQuery();
   query.setSource(ModelUtil.clone(source));
   query.setUpperLimit(upper);
   query.setLowerLimit(lower);
   query.setIncludeAllVersions(allVersions);
   query.setIncludeIncoming(incoming);
   query.setIncludeOutgoing(outgoing);
   query.setIncludeChangePackages(includeCp);
   return query;
 }
 private Version performRegularCommit(
     PrimaryVersionSpec baseVersionSpec,
     LogMessage logMessage,
     final ACUser user,
     final ProjectHistory projectHistory,
     final BranchInfo baseBranch,
     final Version baseVersion,
     final Project newProjectState)
     throws ESUpdateRequiredException, ESException {
   Version newVersion;
   // If branch is null or branch equals base branch, create new
   // version for specific branch
   if (!baseVersionSpec.equals(isHeadOfBranch(projectHistory, baseVersion.getPrimarySpec()))) {
     throw new ESUpdateRequiredException();
   }
   newVersion = createVersion(projectHistory, newProjectState, logMessage, user, baseVersion);
   newVersion.setPreviousVersion(baseVersion);
   baseBranch.setHead(ModelUtil.clone(newVersion.getPrimarySpec()));
   return newVersion;
 }
  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);
  }
  /**
   * Returns all changes within the specified version range for a given project.
   *
   * @param projectId the ID of a project
   * @param source the source version
   * @param target the target version (inclusive)
   * @return a list of change packages containing all the changes for the specified version range
   * @throws InvalidVersionSpecException if an invalid version has been specified
   * @throws ESException in case of failure
   */
  @ESMethod(MethodId.GETCHANGES)
  public List<AbstractChangePackage> getChanges(
      ProjectId projectId, VersionSpec source, VersionSpec target)
      throws InvalidVersionSpecException, ESException {

    sanityCheckObjects(projectId, source, target);
    final PrimaryVersionSpec resolvedSource = resolveVersionSpec(projectId, source);
    final PrimaryVersionSpec resolvedTarget = resolveVersionSpec(projectId, target);
    // if target and source are equal return empty list
    if (resolvedSource.getIdentifier() == resolvedTarget.getIdentifier()) {
      return new ArrayList<AbstractChangePackage>();
    }

    synchronized (getMonitor()) {
      final boolean updateForward = resolvedTarget.getIdentifier() > resolvedSource.getIdentifier();

      // Example: if you want the changes to get from version 5 to 7, you
      // need the changes contained in version 6
      // and 7. The reason is that each version holds the changes which
      // occurred from the predecessor to the
      // version itself. Version 5 holds the changes to get from version 4
      // to 5 and therefore is irrelevant.
      // For that reason the first version is removed, since getVersions
      // always sorts ascending order.
      final List<Version> versions = getVersions(projectId, resolvedSource, resolvedTarget);
      if (versions.size() > 1) {
        versions.remove(0);
      }

      List<AbstractChangePackage> result = new ArrayList<AbstractChangePackage>();
      for (final Version version : versions) {
        final AbstractChangePackage changes = version.getChanges();
        if (changes != null) {
          changes.setLogMessage(ModelUtil.clone(version.getLogMessage()));
          result.add(changes);
        }
      }

      // if source is after target in time
      if (!updateForward) {
        // reverse list and change packages
        final List<AbstractChangePackage> resultReverse = new ArrayList<AbstractChangePackage>();
        for (final AbstractChangePackage changePackage : result) {

          final ChangePackage changePackageReverse =
              VersioningFactory.eINSTANCE.createChangePackage();
          final ESCloseableIterable<AbstractOperation> reversedOperations =
              changePackage.reversedOperations();
          final ArrayList<AbstractOperation> copiedReversedOperations =
              new ArrayList<AbstractOperation>();
          try {
            for (final AbstractOperation op : reversedOperations.iterable()) {
              copiedReversedOperations.add(op.reverse());
            }
          } finally {
            reversedOperations.close();
          }

          for (final AbstractOperation reversedOperation : copiedReversedOperations) {
            changePackageReverse.add(reversedOperation);
          }

          // copy again log message
          // reverse() created a new change package without copying
          // existent attributes
          changePackageReverse.setLogMessage(ModelUtil.clone(changePackage.getLogMessage()));
          resultReverse.add(changePackageReverse);
        }

        Collections.reverse(resultReverse);
        result = resultReverse;
      }

      return result;
    }
  }