Ejemplo n.º 1
0
  private void processDelayedUpdates(
      final List<EntityLinkDesc> delayedUpdates,
      int pos,
      final TransactionItems items,
      final ODataChangeset changeset) {

    for (EntityLinkDesc delayedUpdate : delayedUpdates) {
      pos++;
      items.put(delayedUpdate.getSource(), pos);

      final ODataEntity changes =
          ODataFactory.newEntity(delayedUpdate.getSource().getEntity().getName());

      AttachedEntityStatus status =
          EntityContainerFactory.getContext().entityContext().getStatus(delayedUpdate.getSource());

      final URI sourceURI;
      if (status == AttachedEntityStatus.CHANGED) {
        sourceURI =
            URIUtils.getURI(
                factory.getServiceRoot(),
                delayedUpdate.getSource().getEntity().getEditLink().toASCIIString());
      } else {
        int sourcePos = items.get(delayedUpdate.getSource());
        sourceURI = URI.create("$" + sourcePos);
      }

      for (EntityTypeInvocationHandler target : delayedUpdate.getTargets()) {
        status = EntityContainerFactory.getContext().entityContext().getStatus(target);

        final URI targetURI;
        if (status == AttachedEntityStatus.CHANGED) {
          targetURI =
              URIUtils.getURI(
                  factory.getServiceRoot(), target.getEntity().getEditLink().toASCIIString());
        } else {
          int targetPos = items.get(target);
          targetURI = URI.create("$" + targetPos);
        }

        changes.addLink(
            delayedUpdate.getType() == ODataLinkType.ENTITY_NAVIGATION
                ? ODataFactory.newEntityNavigationLink(delayedUpdate.getSourceName(), targetURI)
                : ODataFactory.newFeedNavigationLink(delayedUpdate.getSourceName(), targetURI));

        LOG.debug(
            "'{}' from {} to {}",
            new Object[] {delayedUpdate.getType().name(), sourceURI, targetURI});
      }

      batchUpdate(delayedUpdate.getSource(), sourceURI, changes, changeset);
    }
  }
Ejemplo n.º 2
0
  private void batchDelete(
      final EntityTypeInvocationHandler handler,
      final ODataEntity entity,
      final ODataChangeset changeset) {

    LOG.debug("Delete '{}'", entity.getEditLink());

    final ODataDeleteRequest req =
        ODataCUDRequestFactory.getDeleteRequest(
            URIUtils.getURI(factory.getServiceRoot(), entity.getEditLink().toASCIIString()));

    if (StringUtils.isNotBlank(handler.getETag())) {
      req.setIfMatch(handler.getETag());
    }

    changeset.addRequest(req);
  }
Ejemplo n.º 3
0
  private void batchUpdate(
      final EntityTypeInvocationHandler handler,
      final ODataEntity changes,
      final ODataChangeset changeset) {

    LOG.debug("Update '{}'", changes.getEditLink());

    final ODataEntityUpdateRequest req =
        ODataCUDRequestFactory.getEntityUpdateRequest(UpdateType.PATCH, changes);
    req.setPrefer(ODataHeaderValues.preferReturnContent);

    if (StringUtils.isNotBlank(handler.getETag())) {
      req.setIfMatch(handler.getETag());
    }

    changeset.addRequest(req);
  }
Ejemplo n.º 4
0
  private void batchUpdateMediaResource(
      final EntityTypeInvocationHandler handler,
      final URI uri,
      final InputStream input,
      final ODataChangeset changeset) {

    LOG.debug("Update media entity '{}'", uri);

    final ODataStreamUpdateRequest req =
        ODataStreamedRequestFactory.getStreamUpdateRequest(uri, input);

    if (StringUtils.isNotBlank(handler.getETag())) {
      req.setIfMatch(handler.getETag());
    }

    changeset.addRequest(req);
  }
Ejemplo n.º 5
0
  private void batchCreate(
      final EntityTypeInvocationHandler handler,
      final ODataEntity entity,
      final ODataChangeset changeset) {

    LOG.debug("Create '{}'", handler);

    final ODataURIBuilder uriBuilder =
        new ODataURIBuilder(factory.getServiceRoot())
            .appendEntitySetSegment(handler.getEntitySetName());
    changeset.addRequest(ODataCUDRequestFactory.getEntityCreateRequest(uriBuilder.build(), entity));
  }
Ejemplo n.º 6
0
  private void batchUpdateMediaEntity(
      final EntityTypeInvocationHandler handler,
      final URI uri,
      final InputStream input,
      final ODataChangeset changeset) {

    LOG.debug("Update media entity '{}'", uri);

    final ODataMediaEntityUpdateRequest req =
        ODataStreamedRequestFactory.getMediaEntityUpdateRequest(uri, input);

    req.setContentType(
        StringUtils.isBlank(handler.getEntity().getMediaContentType())
            ? ODataMediaFormat.WILDCARD.toString()
            : ODataMediaFormat.fromFormat(handler.getEntity().getMediaContentType()).toString());

    if (StringUtils.isNotBlank(handler.getETag())) {
      req.setIfMatch(handler.getETag());
    }

    changeset.addRequest(req);
  }
Ejemplo n.º 7
0
  private void batch(
      final EntityTypeInvocationHandler handler,
      final ODataEntity entity,
      final ODataChangeset changeset) {

    switch (EntityContainerFactory.getContext().entityContext().getStatus(handler)) {
      case NEW:
        batchCreate(handler, entity, changeset);
        break;

      case CHANGED:
        batchUpdate(handler, entity, changeset);
        break;

      case DELETED:
        batchDelete(handler, entity, changeset);
        break;

      default:
        if (handler.isChanged()) {
          batchUpdate(handler, entity, changeset);
        }
    }
  }
Ejemplo n.º 8
0
  /** Transactional changes commit. */
  @Override
  public void flush() {
    final ODataBatchRequest request =
        ODataBatchRequestFactory.getBatchRequest(factory.getServiceRoot());
    final ODataBatchRequest.BatchStreamManager streamManager = request.execute();
    final ODataChangeset changeset = streamManager.addChangeset();

    final TransactionItems items = new TransactionItems();
    final List<EntityLinkDesc> delayedUpdates = new ArrayList<EntityLinkDesc>();

    int pos = 0;

    for (AttachedEntity attachedEntity : EntityContainerFactory.getContext().entityContext()) {
      final AttachedEntityStatus status = attachedEntity.getStatus();
      if (((status != AttachedEntityStatus.ATTACHED && status != AttachedEntityStatus.LINKED)
              || attachedEntity.getEntity().isChanged())
          && !items.contains(attachedEntity.getEntity())) {
        pos++;
        pos =
            processEntityContext(attachedEntity.getEntity(), pos, items, delayedUpdates, changeset);
      }
    }

    processDelayedUpdates(delayedUpdates, pos, items, changeset);

    final ODataBatchResponse response = streamManager.getResponse();

    if (response.getStatusCode() != 202) {
      throw new IllegalStateException("Operation failed");
    }

    final Iterator<ODataBatchResponseItem> iter = response.getBody();

    if (!items.isEmpty()) {
      if (!iter.hasNext()) {
        throw new IllegalStateException("Unexpected operation result");
      }

      final ODataBatchResponseItem item = iter.next();
      if (!(item instanceof ODataChangesetResponseItem)) {
        throw new IllegalStateException(
            "Unexpected batch response item " + item.getClass().getSimpleName());
      }

      final ODataChangesetResponseItem chgres = (ODataChangesetResponseItem) item;

      for (Integer changesetItemId : items.sortedValues()) {
        LOG.debug("Expected changeset item {}", changesetItemId);
        final ODataResponse res = chgres.next();
        if (res.getStatusCode() >= 400) {
          throw new IllegalStateException("Transaction failed: " + res.getStatusMessage());
        }

        final EntityTypeInvocationHandler handler = items.get(changesetItemId);

        if (handler != null) {
          if (res instanceof ODataEntityCreateResponse) {
            LOG.debug("Upgrade created object '{}'", handler);
            handler.setEntity(((ODataEntityCreateResponse) res).getBody());
          } else if (res instanceof ODataEntityUpdateResponse) {
            LOG.debug("Upgrade updated object '{}'", handler);
            handler.setEntity(((ODataEntityUpdateResponse) res).getBody());
          }
        }
      }
    }

    EntityContainerFactory.getContext().detachAll();
  }
Ejemplo n.º 9
0
  private int processEntityContext(
      final EntityTypeInvocationHandler handler,
      int pos,
      final TransactionItems items,
      final List<EntityLinkDesc> delayedUpdates,
      final ODataChangeset changeset) {

    LOG.debug("Process '{}'", handler);

    items.put(handler, null);

    final ODataEntity entity = SerializationUtils.clone(handler.getEntity());
    entity.getNavigationLinks().clear();

    final AttachedEntityStatus currentStatus =
        EntityContainerFactory.getContext().entityContext().getStatus(handler);

    if (AttachedEntityStatus.DELETED != currentStatus) {
      entity.getProperties().clear();
      EngineUtils.addProperties(factory.getMetadata(), handler.getPropertyChanges(), entity);
    }

    for (Map.Entry<NavigationProperty, Object> property : handler.getLinkChanges().entrySet()) {
      final ODataLinkType type =
          Collection.class.isAssignableFrom(property.getValue().getClass())
              ? ODataLinkType.ENTITY_SET_NAVIGATION
              : ODataLinkType.ENTITY_NAVIGATION;

      final Set<EntityTypeInvocationHandler> toBeLinked =
          new HashSet<EntityTypeInvocationHandler>();
      final String serviceRoot = factory.getServiceRoot();

      for (Object proxy :
          type == ODataLinkType.ENTITY_SET_NAVIGATION
              ? (Collection) property.getValue()
              : Collections.singleton(property.getValue())) {

        final EntityTypeInvocationHandler target =
            (EntityTypeInvocationHandler) Proxy.getInvocationHandler(proxy);

        final AttachedEntityStatus status =
            EntityContainerFactory.getContext().entityContext().getStatus(target);

        final URI editLink = target.getEntity().getEditLink();

        if ((status == AttachedEntityStatus.ATTACHED || status == AttachedEntityStatus.LINKED)
            && !target.isChanged()) {
          entity.addLink(
              buildNavigationLink(
                  property.getKey().name(),
                  URIUtils.getURI(serviceRoot, editLink.toASCIIString()),
                  type));
        } else {
          if (!items.contains(target)) {
            pos = processEntityContext(target, pos, items, delayedUpdates, changeset);
            pos++;
          }

          final Integer targetPos = items.get(target);
          if (targetPos == null) {
            // schedule update for the current object
            LOG.debug("Schedule '{}' from '{}' to '{}'", type.name(), handler, target);
            toBeLinked.add(target);
          } else if (status == AttachedEntityStatus.CHANGED) {
            entity.addLink(
                buildNavigationLink(
                    property.getKey().name(),
                    URIUtils.getURI(serviceRoot, editLink.toASCIIString()),
                    type));
          } else {
            // create the link for the current object
            LOG.debug("'{}' from '{}' to (${}) '{}'", type.name(), handler, targetPos, target);

            entity.addLink(
                buildNavigationLink(property.getKey().name(), URI.create("$" + targetPos), type));
          }
        }
      }

      if (!toBeLinked.isEmpty()) {
        delayedUpdates.add(new EntityLinkDesc(property.getKey().name(), handler, toBeLinked, type));
      }
    }

    // insert into the batch
    LOG.debug("{}: Insert '{}' into the batch", pos, handler);
    batch(handler, entity, changeset);

    items.put(handler, pos);

    int startingPos = pos;

    if (handler.getEntity().isMediaEntity()) {

      // update media properties
      if (!handler.getPropertyChanges().isEmpty()) {
        final URI targetURI =
            currentStatus == AttachedEntityStatus.NEW
                ? URI.create("$" + startingPos)
                : URIUtils.getURI(
                    factory.getServiceRoot(), handler.getEntity().getEditLink().toASCIIString());
        batchUpdate(handler, targetURI, entity, changeset);
        pos++;
        items.put(handler, pos);
      }

      // update media content
      if (handler.getStreamChanges() != null) {
        final URI targetURI =
            currentStatus == AttachedEntityStatus.NEW
                ? URI.create("$" + startingPos + "/$value")
                : URIUtils.getURI(
                    factory.getServiceRoot(),
                    handler.getEntity().getEditLink().toASCIIString() + "/$value");

        batchUpdateMediaEntity(handler, targetURI, handler.getStreamChanges(), changeset);

        // update media info (use null key)
        pos++;
        items.put(null, pos);
      }
    }

    for (Map.Entry<String, InputStream> streamedChanges :
        handler.getStreamedPropertyChanges().entrySet()) {
      final URI targetURI =
          currentStatus == AttachedEntityStatus.NEW
              ? URI.create("$" + startingPos)
              : URIUtils.getURI(
                  factory.getServiceRoot(),
                  EngineUtils.getEditMediaLink(streamedChanges.getKey(), entity).toASCIIString());

      batchUpdateMediaResource(handler, targetURI, streamedChanges.getValue(), changeset);

      // update media info (use null key)
      pos++;
      items.put(handler, pos);
    }

    return pos;
  }