/*******************************************************************************
* Copyright (c) 2015 ARM Ltd. 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:
* ARM Ltd and ARM Germany GmbH - Initial API and implementation
*******************************************************************************/
package com.arm.cmsis.pack.rte.components;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import com.arm.cmsis.pack.CpStrings;
import com.arm.cmsis.pack.data.ICpComponent;
import com.arm.cmsis.pack.data.ICpItem;
import com.arm.cmsis.pack.enums.EComponentAttribute;
import com.arm.cmsis.pack.enums.EEvaluationResult;
import com.arm.cmsis.pack.generic.IAttributes;
import com.arm.cmsis.pack.info.ICpComponentInfo;
import com.arm.cmsis.pack.item.CmsisMapItem;
import com.arm.cmsis.pack.rte.RteConstants;
import com.arm.cmsis.pack.rte.dependencies.IRteDependency;
import com.arm.cmsis.pack.utils.AlnumComparator;
/**
* Base class for component hierarchy items
*/
public class RteComponentItem extends CmsisMapItem<IRteComponentItem> implements IRteComponentItem {
protected String fActiveChildName = null;
protected boolean fbActiveChildDefault = true;
protected boolean fbExclusive = true; // default is true
protected EComponentAttribute fComponentAttribute = EComponentAttribute.CNONE;
protected ICpItem fTaxonomy = null;
/**
* Hierarchical constructor
* @param parent parent item
*/
public RteComponentItem(IRteComponentItem parent, final String name) {
super(parent, name);
}
@Override
public void destroy() {
super.destroy();
fTaxonomy = null;
}
@Override
public boolean purge() {
if(!hasChildren()) {
destroy(); // children were already purged
return true;
}
return super.purge();
}
@Override
public void addComponent(ICpComponent cpComponent, int flags) {
// default does nothing
}
@Override
public void addComponent(ICpComponent cpComponent) {
addComponent(cpComponent, RteConstants.NONE);
}
@Override
public Map<String, IRteComponentItem> createMap() {
// entities are sorted alpha-numerically in ascending order
return new TreeMap<String, IRteComponentItem>(new AlnumComparator(false));
}
@Override
public String getItemKey(IRteComponentItem item) {
if(item == null) {
return null;
}
return item.getKey();
}
@Override
public String getKey() {
return getName();
}
@Override
public void addCpItem(ICpItem cpItem) {
if(!hasChildren()) {
return;
}
Collection<? extends IRteComponentItem> children = getChildren();
for(IRteComponentItem child : children) {
child.addCpItem(cpItem);
}
}
@Override
public ICpItem getTaxonomy() {
return fTaxonomy;
}
@Override
public ICpComponent getActiveCpComponent() {
ICpItem item = getActiveCpItem();
if(item instanceof ICpComponent) {
return (ICpComponent) item;
}
return null;
}
@Override
public ICpItem getCpItem() {
return null; // base class does not have associated ICpItem
}
@Override
public boolean isExclusive() {
return fbExclusive;
}
@Override
public boolean isSelected() {
IRteComponent component = getParentComponent();
if(component != null) {
return component.isSelected() && isActive();
}
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.isSelected();
}
if(!hasChildren()) {
return false;
}
Collection<? extends IRteComponentItem> children = getChildren();
for(IRteComponentItem child : children) {
if(child.isSelected()) {
return true;
}
}
return false;
}
@Override
public boolean isActive() {
IRteComponentItem parent = getParent();
if(parent == null)
{
return true; // root is always active
}
if(parent.isExclusive()){
if(parent.getActiveChild() != this) {
return false;
}
}
return parent.isActive();
}
@Override
public String getActiveChildName() {
if(isExclusive() && hasChildren() ) {
if(fActiveChildName == null || !hasChild(fActiveChildName)) {
fActiveChildName = super.getFirstChildKey();
}
}
return fActiveChildName;
}
@Override
public String getFirstChildKey() {
if(isExclusive() && hasChildren() ) {
if(fActiveChildName != null && hasChild(fActiveChildName)) {
return fActiveChildName;
}
}
return super.getFirstChildKey();
}
@Override
public IRteComponentItem getActiveChild() {
if(hasChildren() && isExclusive()) {
String activeChildName = getActiveChildName();
if(fActiveChildName != null) {
return fChildMap.get(activeChildName);
}
}
return null;
}
@Override
public IRteComponentItem getFirstChild() {
IRteComponentItem item = getActiveChild();
if(item != null)
return item;
return super.getFirstChild();
}
@Override
public boolean setActiveChild(final String name) {
if(isExclusive()) {
String newName = name;
String defaultName = getDefaultChildName();
if(name == null || (defaultName != null && name.equals(defaultName))) {
newName = getFirstChildKey();
fbActiveChildDefault = defaultName != null;
} else {
fbActiveChildDefault = false;
}
String activeChildName = getActiveChildName();
if(activeChildName.equals(newName)) {
return false;
}
fActiveChildName = newName;
}
return true;
}
@Override
public ICpItem getActiveCpItem() {
ICpItem cpItem = getCpItem();
if(cpItem != null) {
return cpItem;
}
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getActiveCpItem();
}
return null;
}
@Override
public ICpComponentInfo getActiveCpComponentInfo() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getActiveCpComponentInfo();
}
return null;
}
@Override
public IRteComponentItem getActiveItem() {
ICpItem cpItem = getCpItem();
if(cpItem != null) {
return this;
}
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getActiveItem();
}
return null;
}
@Override
public ICpComponent getApi() {
// default gets parent group active API
IRteComponentGroup group = getParentGroup();
if(group != null) {
return group.getApi();
}
return null;
}
@Override
public IRteComponentGroup getParentGroup() {
IRteComponentItem parent = getParent();
if(parent != null) {
return parent.getParentGroup();
}
return null;
}
@Override
public IRteComponentClass getParentClass() {
IRteComponentItem parent = getParent();
if(parent != null) {
return parent.getParentClass();
}
return null;
}
@Override
public IRteComponentGroup getGroup(IAttributes attributes) {
if(attributes != null) {
String childKey = attributes.getAttribute(getKeyAttributeString());
if(childKey != null && !childKey.isEmpty()) {
IRteComponentItem child = getChild(childKey);
if(child != null) {
return child.getGroup(attributes);
}
}
}
return null;
}
@Override
public IRteComponent getParentComponent() {
IRteComponentItem parent = getParent();
if(parent != null) {
return parent.getParentComponent();
}
return null;
}
@Override
public IRteComponentBundle getParentBundle() {
IRteComponentItem parent = getParent();
if(parent != null) {
return parent.getParentBundle();
}
return null;
}
@Override
public Map<String, ? extends IRteComponentItem> getEffectiveChildMap() {
if(isExclusive()) {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getEffectiveChildMap();
}
return null;
}
return super.getEffectiveChildMap();
}
@Override
public Object[] getEffectiveChildArray() {
if(isExclusive()) {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getEffectiveChildArray();
}
return null;
}
return super.getEffectiveChildArray();
}
@Override
public IRteComponentItem getEffectiveParent() {
IRteComponentItem parent = getParentComponent();
if(parent != null && parent != this) {
IRteComponentItem g = getParentGroup();
if(g.getEffectiveItem() == parent) {
return g;
}
return parent;
}
parent = getParentGroup();
if(parent != null && parent != this && parent.getEffectiveItem() != this) {
return parent;
}
parent = getParentClass();
if(parent != null && parent.getEffectiveItem() != this) {
return parent;
}
return getParent();
}
@Override
public IRteComponentItem getEffectiveHierarchyItem() {
IRteComponentItem component = getParentComponent();
if(component != null) {
IRteComponentItem g = getParentGroup();
if(g.getEffectiveItem() == component) {
return g;
}
return component;
}
IRteComponentItem parent = getParentGroup();
if(parent != null) {
return parent;
}
parent = getParentClass();
if(parent != null) {
return parent;
}
return super.getEffectiveHierarchyItem();
}
@Override
public EComponentAttribute getKeyAttribute() {
return fComponentAttribute;
}
@Override
public String getKeyAttributeString() {
return getKeyAttribute().toString();
}
@Override
public String getKeyAttributeValue(IAttributes attributes) {
if(attributes == null) {
return null;
}
return attributes.getAttribute(getKeyAttributeString());
}
@Override
public String getUrl() {
ICpItem cpItem = getActiveCpItem();
if(cpItem != null) {
String url = cpItem.getUrl();
if(url != null && !url.isEmpty()) {
return url;
}
}
cpItem = getTaxonomy();
if(cpItem != null) {
return cpItem.getUrl();
}
return null;
}
@Override
public String getDoc() {
return getUrl();
}
@Override
public String getDescription() {
ICpItem cpItem = getActiveCpItem();
if(cpItem != null) {
String descr = cpItem.getDescription();
if(descr != null && !descr.isEmpty()) {
return descr;
}
}
cpItem = getTaxonomy();
if(cpItem != null) {
return cpItem.getDescription();
}
return null;
}
@Override
public Collection<String> getVariantStrings() {
// default returns null
return null;
}
@Override
public Collection<String> getVendorStrings() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getVendorStrings();
}
return null;
}
@Override
public Collection<String> getVersionStrings() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getVersionStrings();
}
return null;
}
@Override
public String getActiveVariant() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getActiveVariant();
}
return null;
}
@Override
public void setActiveVariant(String variant) {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
activeChild.setActiveVariant(variant);
}
}
@Override
public String getActiveVendor() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getActiveVendor();
}
return null;
}
@Override
public void setActiveVendor(String vendor) {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
activeChild.setActiveVendor(vendor);
}
}
@Override
public void setActiveVersion(String version) {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
activeChild.setActiveVersion(version);
}
}
@Override
public String getActiveVersion() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getActiveVersion();
}
return null;
}
@Override
public boolean isUseLatestVersion() {
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.isUseLatestVersion();
}
return false;
}
@Override
public String getDefaultChildName() {
// base does not have default child name
return null;
}
@Override
public boolean isActiveChildDefault() {
return fbActiveChildDefault && getDefaultChildName() != null;
}
@Override
public Collection<IRteComponent> getSelectedComponents( Collection<IRteComponent> components) {
if(components == null) {
components = new LinkedList<IRteComponent>();
}
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getSelectedComponents(components);
}
if(hasChildren()) {
Collection<? extends IRteComponentItem> children = getChildren();
for(IRteComponentItem child : children) {
child.getSelectedComponents(components);
}
}
return components;
}
@Override
public Collection<IRteComponent> getUsedComponents( Collection<IRteComponent> components) {
if(components == null) {
components = new LinkedList<IRteComponent>();
}
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getUsedComponents(components);
}
if(hasChildren()) {
Collection<? extends IRteComponentItem> children = getChildren();
for(IRteComponentItem child : children) {
child.getUsedComponents(components);
}
}
return components;
}
@Override
public Collection<IRteComponent> getGeneratorComponents(String generatorId, Collection<IRteComponent> components) {
if(components == null) {
components = new LinkedList<IRteComponent>();
}
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null) {
return activeChild.getGeneratorComponents(generatorId, components);
}
if(hasChildren()) {
Collection<? extends IRteComponentItem> children = getChildren();
for(IRteComponentItem child : children) {
child.getGeneratorComponents(generatorId, components);
}
}
return components;
}
@Override
public EEvaluationResult findComponents(IRteDependency dependency) {
EEvaluationResult result = EEvaluationResult.MISSING;
if(dependency == null) {
return result;
}
Map<String, ? extends IRteComponentItem> children = getChildMap();
if(children == null) {
return result;
}
boolean bIncompatible = false;
String keyPattern = getKeyAttributeValue( dependency.getCpItem().attributes());
int depFlags = dependency.getFlags();
// check if we can ignore Cvarinat, Cversion, Cvendor, CBundle attribute values
boolean ignore = depFlags == 0 ? false : (depFlags | RteConstants.flagForAttribute(getKeyAttributeString())) != 0;
boolean matchFound = false;
// first evaluate active item
IRteComponentItem activeChild = getActiveChild();
if(activeChild != null){
if(ignore || matchKey(keyPattern, activeChild.getName())){
EEvaluationResult res = activeChild.findComponents(dependency);
if(res == EEvaluationResult.FULFILLED) {
return res;
} else if(res != EEvaluationResult.IGNORED ) {
result = res;
}
matchFound = true;
} else if(activeChild.isSelected()) {
bIncompatible = true;
}
}
for(Entry<String, ? extends IRteComponentItem> e : children.entrySet()) {
IRteComponentItem child = e.getValue();
if(child == activeChild) {
continue;
}
if(matchKey(keyPattern, e.getKey())){
matchFound = true;
EEvaluationResult res= child.findComponents(dependency);
if(res != EEvaluationResult.IGNORED && res.ordinal() > result.ordinal()) {
result = res;
}
}
}
if(!matchFound ){
result = EEvaluationResult.valueOf(result, getKeyAttribute());
dependency.addStopItem(this, result);
} else if(bIncompatible && result.ordinal() >= EEvaluationResult.INCOMPATIBLE.ordinal()) {
result = EEvaluationResult.valueOf(EEvaluationResult.INCOMPATIBLE, getKeyAttribute());
dependency.addStopItem(this, result);
}
return result;
}
@Override
public boolean matchKey(String pattern, String key) {
if(pattern == null) {
return true;
}
EComponentAttribute keyAttribute = getKeyAttribute();
if(keyAttribute == null) {
return true;
}
return keyAttribute.match(pattern, key);
}
@Override
public String getDefaultVersion() {
return CpStrings.RteComponentVersionLatest;
}
@Override
public String toString() {
return getName();
}
}