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

io.resys.hdes.client.spi.store.ThenaStoreTemplate Maven / Gradle / Ivy

There is a newer version: 3.130.78
Show newest version
package io.resys.hdes.client.spi.store;

/*-
 * #%L
 * hdes-client-api
 * %%
 * Copyright (C) 2020 - 2023 Copyright 2020 ReSys OÜ
 * %%
 * Licensed 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
 * 
 *      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
 * limitations under the License.
 * #L%
 */


import io.resys.hdes.client.api.HdesStore;
import io.resys.hdes.client.api.ImmutableStoreEntity;
import io.resys.hdes.client.api.ImmutableStoreExceptionMsg;
import io.resys.hdes.client.api.ast.AstBody.AstBodyType;
import io.resys.hdes.client.api.exceptions.StoreException;
import io.resys.hdes.client.spi.store.ThenaConfig.EntityState;
import io.resys.hdes.client.spi.util.HdesAssert;
import io.resys.thena.docdb.api.actions.CommitActions.CommitStatus;
import io.resys.thena.docdb.api.actions.ObjectsActions.ObjectsStatus;
import io.resys.thena.docdb.api.actions.RepoActions.RepoStatus;
import io.smallrye.mutiny.Uni;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public abstract class ThenaStoreTemplate extends PersistenceCommands implements HdesStore {
  public ThenaStoreTemplate(ThenaConfig config) {
    super(config);
  }
  
  protected abstract HdesStore createWithNewConfig(ThenaConfig config);
  
  @Override
  public String getRepoName() {
    return config.getRepoName();
  }
  @Override
  public String getHeadName() {
    return config.getHeadName();
  }
  @Override
  public StoreRepoBuilder repo() {
    return new StoreRepoBuilder() {
      private String repoName;
      private String headName;
      @Override
      public StoreRepoBuilder repoName(String repoName) {
        this.repoName = repoName;
        return this;
      }
      @Override
      public StoreRepoBuilder headName(String headName) {
        this.headName = headName;
        return this;
      }
      @Override
      public Uni create() {
        HdesAssert.notNull(repoName, () -> "repoName must be defined!");
        final var client = config.getClient();
        final var newRepo = client.repo().create().name(repoName).build();
        return newRepo.onItem().transform((repoResult) -> {
          if(repoResult.getStatus() != RepoStatus.OK) {
            throw new StoreException("REPO_CREATE_FAIL", null, 
                ImmutableStoreExceptionMsg.builder()
                .id(repoResult.getStatus().toString())
                .value(repoName)
                .addAllArgs(repoResult.getMessages().stream().map(message->message.getText()).collect(Collectors.toList()))
                .build()); 
          }
          
          return build();
        });
      }
      @Override
      public HdesStore build() {
        HdesAssert.notNull(repoName, () -> "repoName must be defined!");
        return createWithNewConfig(ImmutableThenaConfig.builder()
            .from(config)
            .repoName(repoName)
            .headName(headName == null ? config.getHeadName() : headName)
            .build());
      }
      @Override
      public Uni createIfNot() {
        final var client = config.getClient();
        
        return client.repo().query().id(config.getRepoName()).get().onItem().transformToUni(repo -> {
          if(repo == null) {
            return client.repo().create().name(config.getRepoName()).build().onItem().transform(newRepo -> true); 
          }
          return Uni.createFrom().item(false);
        });
      }
    };
  }
  
  @Override
  public QueryBuilder query() {
    return new DocumentQueryBuilder(config);
  }
  @Override
  public Uni create(CreateStoreEntity newType) {
    final var gid = newType.getId() == null ? gid(newType.getBodyType()) : newType.getId();
    
    final var entity = (StoreEntity) ImmutableStoreEntity.builder()
        .id(gid)
        .hash("")
        .body(newType.getBody())
        .bodyType(newType.getBodyType())
        .build();
    
    if(newType.getId() == null) {
      return super.save(entity);  
    }
    
    return get().onItem().transformToUni(currentState -> {
      cantHaveEntityWithId(newType.getId(), currentState);  
      return super.save(entity);  
    });
  }

  @Override
  public Uni update(UpdateStoreEntity updateType) {
    final Uni query = getEntityState(updateType.getId());
    return query.onItem().transformToUni(state -> {
      final StoreEntity entity = ImmutableStoreEntity.builder()
          .from(state.getEntity())
          .id(updateType.getId())
          .bodyType(state.getEntity().getBodyType())
          .body(updateType.getBody())
          .build();
      return super.save(entity);
    });
  }
  @Override
  public Uni> batch(ImportStoreEntity batchType) {
    return get().onItem().transformToUni(currentState -> {
      final var commitBuilder = config.getClient().commit().head()
          .head(config.getRepoName(), config.getHeadName())
          .message("Save batch with new: " + batchType.getCreate().size() + " and updated: " + batchType.getUpdate().size() + " entries")
          .parentIsLatest()
          .author(config.getAuthorProvider().getAuthor());
      
      final List ids = new ArrayList<>();
      for(final var toBeSaved : batchType.getCreate()) {
        final var id = toBeSaved.getId();
        if(id != null) {
          cantHaveEntityWithId(id, currentState);
        }
        
        final var gid = toBeSaved.getId() == null ? gid(toBeSaved.getBodyType()) : toBeSaved.getId();
        final var entity = (StoreEntity) ImmutableStoreEntity.builder()
            .id(gid)
            .hash("")
            .body(toBeSaved.getBody())
            .bodyType(toBeSaved.getBodyType())
            .build();
        commitBuilder.append(entity.getId(), config.getSerializer().toString(entity));
        ids.add(gid);
      }
      for(final var toBeSaved : batchType.getUpdate()) {
        final var id = toBeSaved.getId();
        HdesAssert.isTrue(
            currentState.getDecisions().containsKey(id) ||
            currentState.getFlows().containsKey(id) ||
            currentState.getServices().containsKey(id) ||
            currentState.getTags().containsKey(id), 
            () -> "Entity not found with id: '" + id + "'!");
        
        final var entity = (StoreEntity) ImmutableStoreEntity.builder()
            .id(id)
            .hash("")
            .body(toBeSaved.getBody())
            .bodyType(toBeSaved.getBodyType())
            .build();
        commitBuilder.append(entity.getId(), config.getSerializer().toString(entity));
        ids.add(entity.getId());
      }    
      
      return commitBuilder.build().onItem().transformToUni(commit -> {
            if(commit.getStatus() == CommitStatus.OK) {
              return config.getClient()
                  .objects().blobState()
                  .repo(config.getRepoName())
                  .anyId(config.getHeadName())
                  .blobNames(ids)
                  .list().onItem()
                  .transform(states -> {
                    if(states.getStatus() != ObjectsStatus.OK) {
                      // TODO
                      throw new StoreException("LIST_FAIL", null, convertMessages2(states));
                    }
                    List entities = new ArrayList<>(); 
                    for(final var state : states.getObjects().getBlob()) {
                      StoreEntity start = (StoreEntity) config.getDeserializer().fromString(state);
                      entities.add(start);
                    }                  
                    return entities;
                  });
            }
            // TODO
            throw new StoreException("SAVE_FAIL", null, convertMessages(commit));
          });
      
    });
    
  }
  @Override
  public Uni> delete(DeleteAstType deleteType) {
    final Uni query = getEntityState(deleteType.getId());
    return query.onItem().transformToUni(state -> delete(state.getEntity()));
  }

  private String gid(AstBodyType type) {
    return config.getGidProvider().getNextId(type);
  }

  @Override
  public HistoryQuery history() {
    // TODO Auto-generated method stub
    return null;
  }
  
  private void cantHaveEntityWithId(String id, StoreState currentState) {
    HdesAssert.isTrue(!currentState.getDecisions().containsKey(id), () -> "Entity of type 'decision' already exists with id: '" + id + "'!");
    HdesAssert.isTrue(!currentState.getFlows().containsKey(id), () -> "Entity of type 'flow' already exists with id: '" + id + "'!");
    HdesAssert.isTrue(!currentState.getServices().containsKey(id), () -> "Entity of type 'service' already exists with id: '" + id + "'!");
    HdesAssert.isTrue(!currentState.getTags().containsKey(id), () -> "Entity of type 'tag' already exists with id: '" + id + "'!");
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy