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

io.resys.wrench.assets.bundle.spi.flow.FlowServiceDataModelBuilder Maven / Gradle / Ivy

package io.resys.wrench.assets.bundle.spi.flow;

import java.sql.Timestamp;

/*-
 * #%L
 * wrench-component-assets
 * %%
 * Copyright (C) 2016 - 2017 Copyright 2016 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 java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.Service;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceAssociation;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceAssociationType;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceDataModel;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceError;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceQuery;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceStatus;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceStore;
import io.resys.wrench.assets.bundle.api.repositories.AssetServiceRepository.ServiceType;
import io.resys.wrench.assets.bundle.spi.beans.ImmutableServiceAssociation;
import io.resys.wrench.assets.bundle.spi.beans.ImmutableServiceDataModel;
import io.resys.wrench.assets.bundle.spi.beans.ImmutableServiceError;
import io.resys.wrench.assets.bundle.spi.builders.GenericServiceQuery;
import io.resys.wrench.assets.datatype.api.DataTypeRepository.DataType;
import io.resys.wrench.assets.datatype.api.DataTypeRepository.Direction;
import io.resys.wrench.assets.datatype.api.DataTypeRepository.ValueType;
import io.resys.wrench.assets.flow.api.model.FlowModel;
import io.resys.wrench.assets.flow.api.model.FlowModel.FlowTaskModel;
import io.resys.wrench.assets.flow.api.model.FlowModel.FlowTaskType;

public class FlowServiceDataModelBuilder {

  private final ServiceStore serviceStore;
  private final List errors = new ArrayList<>();

  public FlowServiceDataModelBuilder(ServiceStore serviceStore) {
    this.serviceStore = serviceStore;
  }

  public ServiceDataModel build(String id, FlowModel flowModel, Timestamp modified) {
    List params = new ArrayList<>(flowModel.getInputs());
    Map allParams = createModelParameterMap(flowModel, params);

    List errors = new ArrayList<>();
    List assocs = new ArrayList<>();

    for(FlowTaskModel taskModel : flowModel.getTasks()) {

      ServiceType serviceType = getServiceType(taskModel);
      if(serviceType != null) {
        String taskServiceName = getTaskServiceName(taskModel);
        if(StringUtils.isEmpty(taskServiceName)) {
          errors.add(new ImmutableServiceError("flowTaskRefMissing", "Task: " + taskModel.getId() + ", is missing 'ref' value!"));
          continue;
        }

        Service service = createQuery().type(serviceType).name(taskServiceName).get().orElse(null);
        if(service == null) {
          errors.add(new ImmutableServiceError("flowTaskRefMissing", "Task: " + taskModel.getId() + ", refers to non existing " + serviceType + ": " + taskServiceName + "!"));
          continue;
        }

        Map taskInputs = getTaskServiceInput(taskModel, allParams, service);
        for(DataType input : service.getDataModel().getParams()) {
          if(input.getDirection() == Direction.OUT) {
            continue;
          }
          if(taskInputs.containsKey(input.getName())) {
            ValueType ref = taskInputs.get(input.getName()).getValueType();
            if(input.getValueType() != ref) {
              errors.add(new ImmutableServiceError("flowTaskParamMissing", "Task: " + taskModel.getId() + ", input: '" + input.getName() + "', type has wrong type, expecting:'" + input.getValueType() + "' but was: '" + ref + "'!"));
            }
            taskInputs.remove(input.getName());
          } else {
            errors.add(new ImmutableServiceError("flowTaskParamMissing", "Task: " + taskModel.getId() + ", is missing input: '" + input.getName() + "'!"));
          }
        }

        for(DataType input : taskInputs.values()) {
          errors.add(new ImmutableServiceError("flowTaskParamUnused", "Task: " + taskModel.getId() + ", has unused input: '" + input.getName() + "'!"));
        }

        if(service.getDataModel().getStatus() == ServiceStatus.ERROR) {
          errors.add(new ImmutableServiceError("flowTaskInError", "Task: " + taskModel.getId() + ", refers to " + serviceType + ", that is in error state!"));
        } else {
          assocs.add(new ImmutableServiceAssociation(taskModel.getId(), taskServiceName, serviceType, isTaskServiceCollection(taskModel) ? ServiceAssociationType.ONE_TO_MANY : ServiceAssociationType.ONE_TO_ONE, Direction.OUT));
        }
      } else if(taskModel.getType() == FlowTaskType.DECISION) {
        for(Map.Entry input : taskModel.getBody().getInputs().entrySet()) {
          if(!allParams.containsKey(input.getKey())) {
            errors.add(new ImmutableServiceError("flowTaskExpressionParamMissing", "Task: " + taskModel.getId() + ", is missing input: '" + input.getKey() + "'!"));
          }
        }
      }
    }

    return new ImmutableServiceDataModel(
        id, flowModel.getId(), flowModel.getDescription(),
        ServiceType.FLOW,
        flowModel.getClass(),
        errors.isEmpty() ? ServiceStatus.OK : ServiceStatus.ERROR,
            Collections.unmodifiableList(errors),
            Collections.unmodifiableList(params),
            Collections.unmodifiableList(assocs));
  }



  protected Map getTaskServiceInput(
      FlowTaskModel taskModel, Map allParams,
      Service refService) {

    Map serviceTypes = refService.getDataModel().getParams().stream()
    .filter(p -> p.getDirection() == Direction.IN)
    .collect(Collectors.toMap(p -> p.getName(), p -> p));

    Map result = new HashMap<>();
    for(Map.Entry entry : taskModel.getBody().getInputs().entrySet()) {
      if(!serviceTypes.containsKey(entry.getKey())) {
        errors.add(new ImmutableServiceError("flowTaskParamUnknown", "Task: " + taskModel.getId() + ", has unknown input: '" + entry.getKey() + "'!"));
      } else if(allParams.containsKey(entry.getValue())) {
        result.put(entry.getKey(), allParams.get(entry.getValue()));
      }
    }
    return result;
  }


  protected Map createModelParameterMap(FlowModel flowModel, List params) {
    Map result = new HashMap<>();
    params.forEach(p -> result.put(p.getName(), p));

    for(FlowTaskModel taskModel : flowModel.getTasks()) {
      String taskServiceName = getTaskServiceName(taskModel);
      ServiceType serviceType = getServiceType(taskModel);
      if(serviceType == null) {
        continue;
      }
      if(StringUtils.isEmpty(taskServiceName)) {
        errors.add(new ImmutableServiceError("flowTaskRefUndefined", "Task: " + taskModel.getId() + ", has no ref!"));
        continue;
      }
      Service service = createQuery().type(serviceType).name(taskServiceName).get().orElse(null);
      if(service == null) {
        errors.add(new ImmutableServiceError("flowTaskRefUndefined", "Task: " + taskModel.getId() + ", ref: '" + taskServiceName + "' does not exist!"));
        continue;
      }
      for(DataType param : service.getDataModel().getParams()) {
        if(param.getDirection() == Direction.OUT) {
          String name = taskModel.getId() + "." + param.getName();
          Assert.isTrue(!result.containsKey(name), "Can't have duplicate param: " + name + "!");
          result.put(name, param);
        }
      }
    }

    return Collections.unmodifiableMap(result);
  }

  protected ServiceQuery createQuery() {
    return new GenericServiceQuery(serviceStore);
  }

  protected boolean isTaskServiceCollection(FlowTaskModel taskModel) {
    return taskModel.getBody() != null ? taskModel.getBody().isCollection() : false;
  }
  protected String getTaskServiceName(FlowTaskModel taskModel) {
    return taskModel.getBody() != null ? taskModel.getBody().getRef() : null;
  }
  protected ServiceType getServiceType(FlowTaskModel taskModel) {
    switch(taskModel.getType()) {
    case DT: return ServiceType.DT;
    case SERVICE: return ServiceType.FLOW_TASK;
    default: return null;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy