/*
*
* * #%L
* * ACS AEM Commons Bundle
* * %%
* * Copyright (C) 2016 Adobe
* * %%
* * 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%
*
*/
package com.adobe.acs.commons.wcm.comparisons.impl.lines;
import com.adobe.acs.commons.wcm.comparisons.lines.Line;
import com.google.common.base.Function;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* LinesGenerator<T> combines two list of values (left and right) to a comparing map. Values with same id are in one line, with different ids in different lines. Example:
* left: A, B, C
* right: B, C, E
* result:
* A | -
* B | B
* C | C
* - | E
* IDs are created with Function<T, Serializable>
*
* @param <T>
*/
public class LinesGenerator<T> {
private final Function<T, Serializable> toId;
private Stepper<T> left;
private Stepper<T> right;
private T leftValue;
private int leftSpacer;
private T rightValue;
private int rightSpacer;
public LinesGenerator(Function<T, Serializable> toId) {
this.toId = toId;
}
public List<Line<T>> generate(final Iterable<T> left, Iterable<T> right) {
this.left = new Stepper<T>(left, toId);
this.right = new Stepper<T>(right, toId);
List<Line<T>> lines = new ArrayList<Line<T>>();
this.leftValue = this.left.next();
this.rightValue = this.right.next();
do {
this.leftSpacer = this.right.positionOfIdAfterCurrent(leftValue);
this.rightSpacer = this.left.positionOfIdAfterCurrent(rightValue);
if (leftValue != null && rightValue != null && toId.apply(leftValue).equals(toId.apply(rightValue))) {
addPair(lines);
} else if (leftSpacer < rightSpacer && leftSpacer > 0) {
addWithLeftSpacers(lines);
} else if (rightSpacer > 0) {
addWithRightSpacers(lines);
} else if (leftSpacer > 0) {
addWithLeftSpacers(lines);
} else {
addSeperated(lines);
}
} while (leftValue != null || rightValue != null);
return lines;
}
private void addSeperated(List<Line<T>> lines) {
if (leftValue != null) {
lines.add(LineImpl.left(leftValue));
leftValue = this.left.next();
}
if (rightValue != null) {
lines.add(LineImpl.right(rightValue));
rightValue = this.right.next();
}
}
private void addWithLeftSpacers(List<Line<T>> lines) {
for (int i = 0; i < leftSpacer; i++) {
lines.add(LineImpl.right(rightValue));
rightValue = this.right.next();
}
}
private void addWithRightSpacers(List<Line<T>> lines) {
for (int i = 0; i < rightSpacer; i++) {
lines.add(LineImpl.left(leftValue));
leftValue = this.left.next();
}
}
private void addPair(List<Line<T>> lines) {
lines.add(LineImpl.both(leftValue, rightValue));
this.leftValue = this.left.next();
this.rightValue = this.right.next();
}
}