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

io.resys.hdes.client.spi.changeset.AstChangesetFactory Maven / Gradle / Ivy

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

/*-
 * #%L
 * hdes-client-api
 * %%
 * Copyright (C) 2020 - 2021 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 java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

import com.google.common.collect.Range;

import io.resys.hdes.client.api.ast.AstChangeset;
import io.resys.hdes.client.api.ast.AstChangeset.CommandsAndChanges;
import io.resys.hdes.client.api.ast.AstCommand;
import io.resys.hdes.client.api.ast.AstCommand.AstCommandValue;
import io.resys.hdes.client.api.ast.ImmutableAstCommand;
import io.resys.hdes.client.api.ast.ImmutableCommandsAndChanges;
import io.resys.hdes.client.spi.changeset.beans.AstChangesetBean;
import io.resys.hdes.client.spi.util.HdesAssert;

public class AstChangesetFactory {

  public static SourceBuilder src() {
    return new SourceBuilder();
  }

  public static CommandsAndChanges src(List src, Integer rev) {
    return new SourceBuilderFromCommands(src, rev).build();
  }

  private static class SourceBuilderFromCommands {
    private final List src; 
    private final Integer rev;
    private final List commands = new ArrayList<>();
    private final SourceBuilder sourceBuilder = new SourceBuilder();
    
    public SourceBuilderFromCommands(List src, Integer rev) {
      this.src = src;
      this.rev = rev;
    }
    
    public CommandsAndChanges build() {
      if (rev != null) {
        int limit = rev;
        int runningVersion = 0;
        for (AstCommand command : src) {
          if (runningVersion++ > limit) {
            break;
          }
          visitCommand(command);
        }
      } else {
        src.forEach(command -> visitCommand(command));
      }
      return ImmutableCommandsAndChanges.builder().commands(commands).src(sourceBuilder.build()).build();
    }
    
    private void visitCommand(AstCommand command) {
      
      AstCommandValue type = command.getType();

      String text = command.getValue();
      if (type == AstCommandValue.DELETE) {
        int line = Integer.parseInt(command.getId());
        sourceBuilder.delete(line, Integer.parseInt(command.getValue()));
      } else if (type == AstCommandValue.ADD) {
        int line = Integer.parseInt(command.getId());
        sourceBuilder.add(line, text);
      } else if(type == AstCommandValue.SET_BODY) {
        String lines[] = text.split("\\r?\\n");
        int lineNumber = 0;
        for(final var lineValue : lines) {
          sourceBuilder.add(lineNumber++, lineValue);  
        }
        
      } else {
        int line = Integer.parseInt(command.getId());
        sourceBuilder.set(line, text);
      }
      commands.add(command);
    }
  }

  public static class SourceBuilder {
    private final List sourcesAdded = new ArrayList<>();
    private final List sourcesDeleted = new ArrayList<>();

    public SourceBuilder add(int line, String value) {
      sourcesAdded.stream().filter(s -> s.getLine() >= line).forEach(s -> s.setLine(s.getLine() + 1));
      sourcesAdded.add(new AstChangesetBean(line,
          ImmutableAstCommand.builder().id(String.valueOf(line)).value(value).type(AstCommandValue.ADD).build()));
      return this;
    }

    public SourceBuilder set(int line, String value) {
      Optional source = sourcesAdded.stream().filter(s -> s.getLine() == line).findFirst();
      HdesAssert.isTrue(source.isPresent(), () -> String.format("Can't change value of non existing line: %s!", line));
      source.get().add(
          ImmutableAstCommand.builder().id(String.valueOf(line)).value(value).type(AstCommandValue.SET).build());
      return this;
    }

    public SourceBuilder delete(int line) {
      Iterator sources = sourcesAdded.iterator();
      while (sources.hasNext()) {
        AstChangesetBean source = sources.next();
        if (source.getLine() == line) {
          sources.remove();
          sourcesDeleted.add(source);
        } else if (source.getLine() > line) {
          source.setLine(source.getLine() - 1);
        }
      }
      return this;
    }

    public SourceBuilder delete(int from, int to) {
      Range range = Range.closed(from, to);
      int linesToDelete = (to - from) + 1;

      Iterator sources = sourcesAdded.iterator();
      while (sources.hasNext()) {
        AstChangesetBean source = sources.next();

        if (range.contains(source.getLine())) {
          sources.remove();
          sourcesDeleted.add(source);
        } else if (source.getLine() > to) {
          source.setLine(source.getLine() - linesToDelete);
        }
      }

      return this;
    }

    public List build() {
      Collections.sort(sourcesAdded);
      return new ArrayList<>(sourcesAdded);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy