org.opencompare.api.java.impl.PCMImpl Maven / Gradle / Ivy
The newest version!
package org.opencompare.api.java.impl;
import java.util.*;
import org.opencompare.api.java.*;
import org.opencompare.api.java.exception.MergeConflictException;
import org.opencompare.api.java.util.*;
/**
* Created by gbecan on 08/10/14.
*/
public class PCMImpl implements PCM {
private org.opencompare.model.PCM kpcm;
public PCMImpl(org.opencompare.model.PCM kpcm) {
this.kpcm = kpcm;
}
public org.opencompare.model.PCM getKpcm() {
return kpcm;
}
@Override
public String getName() {
return kpcm.getName();
}
@Override
public void setName(String s) {
kpcm.setName(s);
}
@Override
public List getProducts() {
List products = new ArrayList();
for (org.opencompare.model.Product kProduct : kpcm.getProducts()) {
products.add(new ProductImpl(kProduct));
}
return products;
}
@Override
public Feature getProductsKey() {
org.opencompare.model.Feature key = kpcm.getProductsKey();
return key == null ? null : new FeatureImpl(key);
}
@Override
public void setProductsKey(Feature feature) {
kpcm.setProductsKey(((FeatureImpl) feature).getkFeature());
}
@Override
public void addProduct(Product product) {
kpcm.addProducts(((ProductImpl) product).getkProduct());
}
@Override
public void removeProduct(Product product) {
kpcm.removeProducts(((ProductImpl) product).getkProduct());
}
@Override
public List getFeatures() {
List features = new ArrayList();
for (org.opencompare.model.AbstractFeature kFeature : kpcm.getFeatures()) {
if (kFeature instanceof org.opencompare.model.Feature) {
features.add(new FeatureImpl((org.opencompare.model.Feature) kFeature));
} else if (kFeature instanceof org.opencompare.model.FeatureGroup) {
features.add(new FeatureGroupImpl((org.opencompare.model.FeatureGroup) kFeature));
}
}
return features;
}
@Override
public void addFeature(AbstractFeature abstractFeature) {
kpcm.addFeatures(((AbstractFeatureImpl) abstractFeature).getkAbstractFeature());
}
@Override
public void removeFeature(AbstractFeature abstractFeature) {
kpcm.removeFeatures(((AbstractFeatureImpl) abstractFeature).getkAbstractFeature());
}
@Override
public List getConcreteFeatures() {
List aFeatures = this.getFeatures();
List features = new ArrayList();
for (AbstractFeature aFeature : aFeatures) {
features.addAll(getConcreteFeatures(aFeature));
}
return features;
}
private List getConcreteFeatures(AbstractFeature aFeature) {
List features = new ArrayList();
if (aFeature instanceof FeatureGroup) {
FeatureGroup featureGroup = (FeatureGroup) aFeature;
for (AbstractFeature subFeature : featureGroup.getFeatures()) {
features.addAll(getConcreteFeatures(subFeature));
}
} else {
features.add((Feature) aFeature);
}
return features;
}
@Override
public Feature getOrCreateFeature(String name, PCMFactory factory) {
// Return the feature if it exists
List features = this.getConcreteFeatures();
for (Feature feature : features) {
if (feature.getName().equals(name)) {
return feature;
}
}
// The feature does not exists, we create a new feature
Feature newFeature = factory.createFeature();
newFeature.setName(name);
this.addFeature(newFeature);
return newFeature;
}
@Override
public Product getOrCreateProduct(String name, PCMFactory factory) {
// Return the product if it exists
List products = this.getProducts();
for (Product product : products) {
if (product.getKeyContent().equals(name)) {
return product;
}
}
// The product does not exists, we create a new product
Product newProduct = factory.createProduct();
this.addProduct(newProduct);
return newProduct;
}
@Override
public void accept(PCMVisitor visitor) {
visitor.visit(this);
}
@Override
public void merge(PCM pcm, PCMFactory factory) throws MergeConflictException {
mergeFeatures(this.getFeatures(), pcm.getFeatures(), null, factory);
mergeProducts(pcm, factory);
mergeCells(pcm, factory);
}
private void addNewFeatures(PCM pcm, PCMFactory factory) {
for (AbstractFeature aFeature : pcm.getFeatures()) { // TODO : check usage of getFeatures()
// Check if the feature already exists in this PCM
boolean existInThis = false;
for (AbstractFeature aFeatureInThis : this.getFeatures()) { // TODO : check usage of getFeatures()
if (aFeature.equals(aFeatureInThis)) {
existInThis = true;
break;
}
}
// Copy feature from merged PCM if the feature is new
if (!existInThis) {
AbstractFeature newFeature;
if (aFeature instanceof Feature) {
newFeature = factory.createFeature();
} else {
newFeature = factory.createFeatureGroup();
// TODO : handle sub features
}
newFeature.setName(aFeature.getName());
this.addFeature(newFeature);
}
}
}
private void mergeFeatures(List featuresPCM1, List featuresPCM2, FeatureGroup parent, PCMFactory factory) {
for (AbstractFeature feature2 : featuresPCM2) {
AbstractFeature equivalentFeature = null;
for (AbstractFeature feature1 : featuresPCM1) {
boolean sameFeatures = feature1.equals(feature2);
boolean sameTypes = (feature1 instanceof Feature && feature2 instanceof Feature) ||
(feature1 instanceof FeatureGroup && feature2 instanceof FeatureGroup);
if (sameFeatures && sameTypes) {
equivalentFeature = feature1;
}
}
if (equivalentFeature != null) {
if (equivalentFeature instanceof FeatureGroup && feature2 instanceof FeatureGroup) {
FeatureGroup featureGroup1 = (FeatureGroup) equivalentFeature;
FeatureGroup featureGroup2 = (FeatureGroup) feature2;
mergeFeatures(featureGroup1.getFeatures(), featureGroup2.getFeatures(), featureGroup1, factory);
}
} else {
AbstractFeature feature2Copy = (AbstractFeature) feature2.clone(factory);
if (parent == null) {
this.addFeature(feature2Copy);
} else {
parent.addFeature(feature2Copy);
}
}
}
}
private void mergeProducts(PCM pcm, PCMFactory factory) {
for (Product product : pcm.getProducts()) {
// Check if the product already exists in this PCM
boolean existInThis = false;
for (Product productInThis : this.getProducts()) {
if (product.getKeyContent().equals(productInThis.getKeyContent())) {
existInThis = true;
break;
}
}
// Copy product from merged PCM if the product is new
if (!existInThis) {
Product newProduct = factory.createProduct();
this.addProduct(newProduct);
}
}
}
private void mergeCells(PCM pcm, PCMFactory factory) throws MergeConflictException {
for (Product product : this.getProducts()) {
for (Feature feature : this.getConcreteFeatures()) {
Cell cellInThis = product.findCell(feature);
Cell cellInPCM = findCorrespondingCell(pcm, product, feature);
if (cellInThis == null && cellInPCM == null) {
// Create empty cell
Cell newCell = factory.createCell();
newCell.setContent("N/A");
newCell.setFeature(feature);
newCell.setInterpretation(factory.createNotAvailable());
product.addCell(newCell);
} else if (cellInThis == null) {
// Copy cell from 'pcm'
Cell newCell = factory.createCell();
newCell.setContent(cellInPCM.getContent());
newCell.setFeature(feature);
// TODO : copy interpretation
product.addCell(newCell);
} else if (cellInPCM == null) {
// Nothing to do
} else if (cellInThis.getContent().equals(cellInPCM.getContent())) {
// Nothing to do
} else {
// Conflict
throw new MergeConflictException();
}
}
}
}
private Cell findCorrespondingCell(PCM pcm, Product product, Feature feature) {
Cell correspondingCell = null;
// Find corresponding feature
Feature correspondingFeature = null;
for (Feature featureInPCM : pcm.getConcreteFeatures()) {
if (featureInPCM.getName().equals(feature.getName())) {
correspondingFeature = featureInPCM;
break;
}
}
// Find corresponding cell
for (Product productInPCM : pcm.getProducts()) {
if (productInPCM.getKeyContent().equals(product.getKeyCell())) {
correspondingCell = productInPCM.findCell(correspondingFeature);
break;
}
}
return correspondingCell;
}
@Override
public boolean isValid() {
// List features
List features = getConcreteFeatures();
// Check uniqueness of features
Set uniqueFeatures = new HashSet(features);
if (uniqueFeatures.size() != features.size()) {
return false;
}
// Check uniqueness of products
Set uniqueProducts = new HashSet<>(this.getProducts());
if (uniqueProducts.size() != this.getProducts().size()) {
return false;
}
// Check that a cell exists for each pair of products and features.
for (Product product : this.getProducts()) {
for (Feature feature : features) {
if (product.findCell(feature) == null) {
return false;
}
}
}
return true;
}
@Override
public void normalize(PCMFactory factory) {
for (Product product : this.getProducts()) {
for (Feature feature : this.getConcreteFeatures()) {
if (product.findCell(feature) == null) {
Cell cell = factory.createCell();
cell.setFeature(feature);
cell.setContent("N/A");
cell.setInterpretation(factory.createNotAvailable());
product.addCell(cell);
}
}
}
}
@Override
public DiffResult diff(PCM pcm, PCMElementComparator pcmElementComparator) {
DiffResult result = new DiffResult(this, pcm);
List thisFeatures = this.getConcreteFeatures();
List pcmFeatures = pcm.getConcreteFeatures();
// Compare features
Map equivalentFeatures = diffFeatures(thisFeatures, pcmFeatures, pcmElementComparator, result);
// FIXME : feature groups are not supported
// Compare products
Map equivalentProducts = diffProducts(this.getProducts(), pcm.getProducts(), pcmElementComparator, result);
// Compare cells of common products and features
compareCells(equivalentFeatures, equivalentProducts, pcmElementComparator, result);
return result;
}
/**
* Compare the features of two PCMs
* @param pcm1Features
* @param pcm2Features
* @param comparator
* @param result
* @return equivalent features
*/
private Map diffFeatures(List pcm1Features, List pcm2Features, PCMElementComparator comparator, DiffResult result) {
List commonFeatures = new ArrayList();
List featuresOnlyInPCM1 = new ArrayList();
List featuresOnlyInPCM2 = new ArrayList(pcm2Features);
Map equivalentFeatures = new HashMap();
for (Feature f1 : pcm1Features) {
boolean similarFeature = false;
for (Feature f2 : pcm2Features) {
similarFeature = comparator.similarFeature(f1, f2);
if (similarFeature) {
commonFeatures.add(f1);
featuresOnlyInPCM2.remove(f2);
equivalentFeatures.put(f1, f2);
break;
}
}
if (!similarFeature) {
featuresOnlyInPCM1.add(f1);
}
}
result.setCommonFeatures(commonFeatures);
result.setFeaturesOnlyInPCM1(featuresOnlyInPCM1);
result.setFeaturesOnlyInPCM2(featuresOnlyInPCM2);
return equivalentFeatures;
}
/**
* Compare the products of two PCMs
* @param pcm1Products
* @param pcm2Products
* @param comparator
* @param result
* @return equivalent products
*/
private Map diffProducts(List pcm1Products, List pcm2Products, PCMElementComparator comparator, DiffResult result) {
List commonProducts = new ArrayList();
List productsOnlyInPCM1 = new ArrayList();
List productsOnlyInPCM2 = new ArrayList(pcm2Products);
Map equivalentProducts = new HashMap();
for (Product p1 : pcm1Products) {
boolean similarProduct = false;
for (Product p2 : pcm2Products) {
similarProduct = comparator.similarProduct(p1, p2);
if (similarProduct) {
commonProducts.add(p1);
productsOnlyInPCM2.remove(p2);
equivalentProducts.put(p1, p2);
break;
}
}
if (!similarProduct) {
productsOnlyInPCM1.add(p1);
}
}
result.setCommonProducts(commonProducts);
result.setProductsOnlyInPCM1(productsOnlyInPCM1);
result.setProductsOnlyInPCM2(productsOnlyInPCM2);
return equivalentProducts;
}
private void compareCells(Map equivalentFeatures, Map equivalentProducts, PCMElementComparator comparator, DiffResult result) {
List> differingCells = new ArrayList>();
for (Feature f1 : result.getCommonFeatures()) {
Feature f2 = equivalentFeatures.get(f1);
for (Product p1 : result.getCommonProducts()) {
Product p2 = equivalentProducts.get(p1);
Cell c1 = p1.findCell(f1);
Cell c2 = p2.findCell(f2);
if (!comparator.similarCell(c1, c2)) {
differingCells.add(new Pair(c1, c2));
}
}
}
result.setDifferingCells(differingCells);
}
@Override
public void invert(PCMFactory factory) {
// Save original features and products
Feature productsKey = this.getProductsKey();
List originalFeatures = this.getConcreteFeatures();
List originalProducts = this.getProducts();
// Clean PCM
for (AbstractFeature originalFeature : this.getFeatures()) {
this.removeFeature(originalFeature);
}
for (Product originalProduct : originalProducts) {
this.removeProduct(originalProduct);
}
// Restore products' key
this.addFeature(productsKey);
// Create new features
Map productToFeature = new HashMap<>(); // Mapping between original products and new features
for (Cell cell : productsKey.getCells()) {
Feature feature = factory.createFeature();
feature.setName(cell.getContent());
this.addFeature(feature);
productToFeature.put(cell.getProduct(), feature);
}
// Create new products and their corresponding key cell
Map featureToProduct = new HashMap<>(); // Mapping between original features and new products
for (Feature originalFeature : originalFeatures) {
if (!originalFeature.equals(productsKey)) {
Cell cell = factory.createCell();
cell.setContent(originalFeature.getName());
cell.setFeature(productsKey);
Product product = factory.createProduct();
product.addCell(cell);
this.addProduct(product);
featureToProduct.put(originalFeature, product);
}
}
// FIXME : feature groups ???
// Create new cells
for (Feature originalFeature : originalFeatures) {
if (!originalFeature.equals(productsKey)) {
for (Cell cell : originalFeature.getCells()) {
Feature newFeature = productToFeature.get(cell.getProduct());
Product newProduct = featureToProduct.get(cell.getFeature());
Cell newCell = factory.createCell();
newCell.setContent(cell.getContent());
newCell.setRawContent(cell.getRawContent());
newCell.setInterpretation(cell.getInterpretation());
newCell.setFeature(newFeature);
newProduct.addCell(newCell);
}
}
}
}
@Override
public int getFeaturesDepth() {
int depth = 1;
for (AbstractFeature abstractFeature: getFeatures()) {
if (abstractFeature instanceof FeatureGroup) {
FeatureGroup featureGroup = (FeatureGroup) abstractFeature;
int subdepth = featureGroup.getDepth();
if (subdepth > depth) {
depth = subdepth;
}
}
}
return depth;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PCMImpl pcm = (PCMImpl) o;
if (this.getName() == null && pcm.getName() != null) {
return false;
}
if (this.getName() != null && !this.getName().equals(pcm.getName())) {
return false;
}
Set thisConcreteFeaturesSet = new HashSet<>(this.getConcreteFeatures());
Set pcmConcreteFeaturesSet = new HashSet<>(pcm.getConcreteFeatures());
if (!thisConcreteFeaturesSet.equals(pcmConcreteFeaturesSet)) {
return false;
}
Set thisProductSet = new HashSet<>(this.getProducts());
Set pcmProductSet = new HashSet<>(pcm.getProducts());
if (!thisProductSet.equals(pcmProductSet)) {
return false;
}
return true;
}
@Override
public int hashCode() {
return Objects.hash(this.getName(), new HashSet(this.getConcreteFeatures()), new HashSet(this.getProducts()));
}
@Override
public PCMElement clone(PCMFactory factory) {
PCM copy = factory.createPCM();
copy.setName(this.getName());
for (AbstractFeature feature : this.getFeatures()) {
copy.addFeature((AbstractFeature) feature.clone(factory));
}
for (Product product : this.getProducts()) {
Product productCopy = (Product) product.clone(factory);
copy.addProduct(productCopy);
}
return copy;
}
@Override
public String toString() {
return "PCMImpl{" +
"name= " + this.getName() +
",#features= " + this.getConcreteFeatures().size() +
", #products= " + this.getProducts().size() +
", products' key= " + this.getProductsKey() +
"}";
}
}
| © 2015 - 2025 Weber Informatics LLC | Privacy Policy