package org.specmath.restapi;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.specmath.library.Conflict;
import org.specmath.library.SpecMath;
import org.specmath.library.UnexpectedTypeException;
import org.specmath.library.UnionConflictException;
import org.specmath.library.UnionOptions;
import org.specmath.restapi.model.MergeConflict;
import org.specmath.restapi.model.MergeRequest;
import org.specmath.restapi.model.OperationResponse;
import org.specmath.restapi.model.OverlayRequest;

/**
 * Service functions which handle Spec Math related requests to the API
 */
public class SpecMathService {

  OperationResponse handleMergeRequest(MergeRequest mergeRequest) {
    OperationResponse ret = new OperationResponse();

    try {
      String resultSpec = performUnionOperation(mergeRequest);

      ret.setResult(resultSpec);
      ret.setStatus("success");

      return ret;
    } catch (UnionConflictException e) {
      List<MergeConflict> mergeConflicts = castMergeConflictObject(e);

      ret.setStatus("conflicts");
      ret.setConflicts(mergeConflicts);

      return ret;
    } catch (Exception e) {
      ret.setStatus("operation error");

      return ret;
    }
  }

  OperationResponse handleOverlayRequest(OverlayRequest overlayRequest) {
    OperationResponse ret = new OperationResponse();
    try {
      String resultSpec = performOverlayOperation(overlayRequest);

      ret.setResult(resultSpec);
      ret.setStatus("success");

      return ret;
    } catch (Exception e) {
      ret.setStatus("operation error");
      return ret;
    }
  }

  /**
   * Class function for the static SpecMath function, used for mocking purposes
   */
  String performOverlayOperation(OverlayRequest overlayRequest) throws UnexpectedTypeException {
    return SpecMath.applyOverlay(overlayRequest.getOverlay(), overlayRequest.getSpec());
  }

  /**
   * Cast the conflict objects in {@code e} to {@code MergeConflict} objects
   */
  private List<MergeConflict> castMergeConflictObject(UnionConflictException e) {
    List<MergeConflict> mergeConflicts = new ArrayList<>();

    for (Conflict conflict : e.getConflicts()) {
      MergeConflict mergeConflict = new MergeConflict();
      mergeConflict.setOptions(conflict.getOptions().stream().map(Object::toString).collect(
          Collectors.toList()));
      mergeConflict.setKeypath(conflict.getKeypath());
      mergeConflicts.add(mergeConflict);
    }

    return mergeConflicts;
  }

  /**
   * Performs the union operation by creating the {@code UnionOptions} and other parameters needed
   */
  String performUnionOperation(MergeRequest mergeRequest)
      throws IOException, UnionConflictException, UnexpectedTypeException {
    String conflictRes = castConflictResolutionsToString(mergeRequest);
    String defaults = mergeRequest.getDefaults() == null ? "" : mergeRequest.getDefaults();

    UnionOptions unionOptions = UnionOptions.builder().defaults(defaults)
        .conflictResolutions(conflictRes).build();

    List<String> specs = mergeRequest.getSpecs();

    return SpecMath.union(specs, unionOptions);
  }

  /**
   * Turn the incoming conflict resolutions object into a string to be used by the Spec Math
   * Library
   */
  private String castConflictResolutionsToString(MergeRequest mergeRequest)
      throws JsonProcessingException {
    if (mergeRequest.getConflictResolutions() != null) {
      ObjectMapper mapper = new ObjectMapper();
      return mapper.writeValueAsString(mergeRequest.getConflictResolutions());
    }
    return "";
  }
}

@@ -1771,55 +1771,150 @@
   * 
-Class function for the static
+Performs the overlay operation by extracting the parameters from the overlayRequest object and%0A   * and calling the
  Spec
+ 
 Math 
+Library 
 function
 , us
@@ -1913,35 +1913,8 @@
 tion
-, used for mocking purposes
 %0A   
@@ -2122,1229 +2122,1277 @@
   * 
-Cast the conflict objects in %7B@code e%7D to %7B@code MergeConflict%7D objects%0A   */%0A  private List%3CMergeConflict%3E castMergeConflictObject(UnionConflictException e) %7B%0A    List%3CMergeConflict%3E mergeConflicts = new ArrayList%3C%3E();%0A%0A    for (Conflict conflict : e.getConflicts()) %7B%0A      MergeConflict mergeConflict = new MergeConflict();%0A      mergeConflict.setOptions(conflict.getOptions().stream().map(Object::toString).collect(%0A          Collectors.toList()));%0A      mergeConflict.setKeypath(conflict.getKeypath());%0A      mergeConflicts.add(mergeConflict);%0A    %7D%0A%0A    return mergeConflicts;%0A  %7D%0A%0A  /**%0A   * Performs the union operation by creating the %7B@code UnionOptions%7D and other parameters needed%0A   */%0A  String performUnionOperation(MergeRequest mergeRequest)%0A      throws IOException, UnionConflictException, UnexpectedTypeException %7B%0A    String conflictRes = castConflictResolutionsToString(mergeRequest);%0A    String defaults = mergeRequest.getDefaults() == null ? %22%22 : mergeRequest.getDefaults();%0A%0A    UnionOptions unionOptions = UnionOptions.builder().defaults(defaults)%0A        .conflictResolutions(conflictRes).build();%0A%0A    List%3CString%3E specs = mergeRequest.getSpecs();%0A%0A    return SpecMath.union(specs, unionOptions)
+Performs the union operation by creating the %7B@code UnionOptions%7D and other parameters needed%0A   * and calling the Spec Math Library function%0A   */%0A  String performUnionOperation(MergeRequest mergeRequest)%0A      throws IOException, UnionConflictException, UnexpectedTypeException %7B%0A    String conflictRes = castConflictResolutionsToString(mergeRequest);%0A    String defaults = mergeRequest.getDefaults() == null ? %22%22 : mergeRequest.getDefaults();%0A%0A    UnionOptions unionOptions = UnionOptions.builder().defaults(defaults)%0A        .conflictResolutions(conflictRes).build();%0A%0A    List%3CString%3E specs = mergeRequest.getSpecs();%0A%0A    return SpecMath.union(specs, unionOptions);%0A  %7D%0A%0A  /**%0A   * Cast the conflict objects in %7B@code e%7D to %7B@code MergeConflict%7D objects%0A   */%0A  private List%3CMergeConflict%3E castMergeConflictObject(UnionConflictException e) %7B%0A    List%3CMergeConflict%3E mergeConflicts = new ArrayList%3C%3E();%0A%0A    for (Conflict conflict : e.getConflicts()) %7B%0A      MergeConflict mergeConflict = new MergeConflict();%0A      mergeConflict.setOptions(conflict.getOptions().stream().map(Object::toString).collect(%0A          Collectors.toList()));%0A      mergeConflict.setKeypath(conflict.getKeypath());%0A      mergeConflicts.add(mergeConflict);%0A    %7D%0A%0A    return mergeConflicts
 ;%0A  

rearrange and rewrite javadoc