blob: e9c730399a3f6b7ab59d44c0cfeee1423f331a03 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.help.internal.criteria;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.help.IUAElement;
import org.eclipse.help.internal.UAElement;
/*
* Assembles individual criteria definition contributions into a complete, fully
* criteria definition.
*/
public class CriteriaDefinitionAssembler {
/*
* Assembles the given criteria definition contributions into a complete criteria definition.
* The originals are not modified.
*/
public CriteriaDefinition assemble(List contributions) {
return merge(contributions);
}
/*
* Merge all criteria definition contributions into one.
*/
private CriteriaDefinition merge(List contributions) {
CriteriaDefinition criteriaDefinition = new CriteriaDefinition();
Iterator iter = contributions.iterator();
while (iter.hasNext()) {
CriteriaDefinitionContribution contribution = (CriteriaDefinitionContribution)iter.next();
mergeChildren(criteriaDefinition, (CriteriaDefinition)contribution.getCriteriaDefinition());
contribution.setCriteriaDefinition(null);
}
return criteriaDefinition;
}
/*
* Merges the children of nodes a and b, and stores them into a. If the two
* contain the same criterion id, only one is kept but its children are merged,
* recursively. In one criterion, if multiple criterion values exist with the
* same id, only the first one found is kept.
*
* Insure criterion has its id at least, and criterion value has both its id and name.
*/
private void mergeChildren(UAElement a, UAElement b) {
Map criterionById = new HashMap();
Set criterionValueIds = new HashSet();
IUAElement[] childrenA = a.getChildren();
for(int i = 0; i < childrenA.length; ++i){
UAElement childA = (UAElement)childrenA[i];
if(childA instanceof CriterionDefinition) {
String id = childA.getAttribute(CriterionDefinition.ATTRIBUTE_ID);
if(null != id && id.trim().length() > 0) {
criterionById.put(childA.getAttribute(CriterionDefinition.ATTRIBUTE_ID), childA);
}
} else if(childA instanceof CriterionValueDefinition) {
String valueId = childA.getAttribute(CriterionValueDefinition.ATTRIBUTE_ID);
String valueName = childA.getAttribute(CriterionValueDefinition.ATTRIBUTE_NAME);
if(null != valueId && valueId.trim().length() > 0 && null != valueName && valueName.trim().length() > 0){
criterionValueIds.add(childA.getAttribute(CriterionValueDefinition.ATTRIBUTE_ID));
}
}
}
IUAElement[] childrenB = b.getChildren();
for(int i = 0; i < childrenB.length; ++i){
UAElement childB = (UAElement) childrenB[i];
if(childB instanceof CriterionDefinition) {
String idB = childB.getAttribute(CriterionDefinition.ATTRIBUTE_ID);
if(null != idB && idB.trim().length() > 0){
if (criterionById.containsKey(idB)) {
// duplicate id; merge children
mergeChildren((CriterionDefinition)criterionById.get(idB), childB);
} else {
// wasn't a duplicate
a.appendChild(childB);
criterionById.put(idB, childB);
}
}
} else if(childB instanceof CriterionValueDefinition) {
String valueIdB = childB.getAttribute(CriterionValueDefinition.ATTRIBUTE_ID);
String valueNameB = childB.getAttribute(CriterionValueDefinition.ATTRIBUTE_NAME);
if(null != valueIdB && valueIdB.trim().length() > 0 && null != valueNameB && valueNameB.trim().length() > 0){
if (!criterionValueIds.contains(valueIdB)) {
// For one criterion, add criterion value only if id doesn't exist yet
a.appendChild(childB);
criterionValueIds.add(valueIdB);
}
}
}
}
}
}