/*******************************************************************************
* 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;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.arm.cmsis.pack.CpPlugIn;
import com.arm.cmsis.pack.ICpEnvironmentProvider;
import com.arm.cmsis.pack.ICpPackManager;
import com.arm.cmsis.pack.common.CmsisConstants;
import com.arm.cmsis.pack.data.CpPackFilter;
import com.arm.cmsis.pack.data.ICpComponent;
import com.arm.cmsis.pack.data.ICpDeviceItem;
import com.arm.cmsis.pack.data.ICpGenerator;
import com.arm.cmsis.pack.data.ICpItem;
import com.arm.cmsis.pack.data.ICpPack;
import com.arm.cmsis.pack.data.ICpPackCollection;
import com.arm.cmsis.pack.data.ICpPackFilter;
import com.arm.cmsis.pack.enums.EEvaluationResult;
import com.arm.cmsis.pack.enums.EVersionMatchMode;
import com.arm.cmsis.pack.events.RteEvent;
import com.arm.cmsis.pack.events.RteEventProxy;
import com.arm.cmsis.pack.generic.Attributes;
import com.arm.cmsis.pack.generic.IAttributes;
import com.arm.cmsis.pack.info.ICpComponentInfo;
import com.arm.cmsis.pack.info.ICpConfigurationInfo;
import com.arm.cmsis.pack.info.ICpDeviceInfo;
import com.arm.cmsis.pack.info.ICpPackFilterInfo;
import com.arm.cmsis.pack.info.ICpPackInfo;
import com.arm.cmsis.pack.rte.components.IRteComponent;
import com.arm.cmsis.pack.rte.components.IRteComponentItem;
import com.arm.cmsis.pack.rte.dependencies.IRteDependencyItem;
import com.arm.cmsis.pack.rte.devices.IRteDeviceItem;
import com.arm.cmsis.pack.rte.packs.IRtePack;
import com.arm.cmsis.pack.rte.packs.IRtePackCollection;
import com.arm.cmsis.pack.rte.packs.IRtePackFamily;
import com.arm.cmsis.pack.rte.packs.RtePackCollection;
/**
* Default implementation of IRteModelController interface
*
*/
public abstract class RteModelController extends RteEventProxy implements IRteModelController {
protected IRteModel fModel = null;
// filtered Packs
protected ICpPackFilter fSavedPackFilter = null;
protected ICpPackFilter fCurrentPackFilter = null;
protected IRtePackCollection fRtePackCollection = null;
protected IAttributes fSavedDeviceAttributes = null;
protected Set<String> fSavedComponentKeys = null;
protected Set<String> fSavedGpdscFiles = null;
protected boolean fbComponentSelectionModified = false;
protected boolean fbPackFilterModified = false;
protected boolean fbDeviceModified = false;
/**
* Default constructor
*/
public RteModelController(IRteModel model) {
fModel = model;
}
@Override
public IRteModel getModel() {
return fModel;
}
//@Override
@Override
public void clear() {
if(fModel != null) {
fModel.clear();
}
fModel = null;
fSavedPackFilter = null;
fCurrentPackFilter = null;
fRtePackCollection = null;
fSavedDeviceAttributes = null;
fSavedComponentKeys = null;
fSavedGpdscFiles = null;
}
@Override
public boolean isComponentSelectionModified() {
return fbComponentSelectionModified;
}
@Override
public boolean isPackFilterModified() {
return fbPackFilterModified;
}
@Override
public boolean isDeviceModified() {
return fbDeviceModified;
}
protected boolean isGpdscFileListModified() {
Map<String, ICpPack> genPacks = getGeneratedPacks();
if(fSavedGpdscFiles == null)
return genPacks != null && !genPacks.isEmpty() ;
if (genPacks == null)
return fSavedGpdscFiles != null && !fSavedGpdscFiles.isEmpty() ;
return !fSavedGpdscFiles.equals(genPacks.keySet());
}
protected Set<String> collectGpdscFiles() {
Map<String, ICpPack> genPacks = getGeneratedPacks();
if(genPacks == null || genPacks.isEmpty()) {
return null;
}
return new HashSet<String>(genPacks.keySet());
}
@Override
public boolean isModified() {
return isDeviceModified() || isPackFilterModified() || isComponentSelectionModified();
}
protected boolean checkIfComponentsModified() {
Set<String> keys = collectComponentKeys();
return !keys.equals(fSavedComponentKeys);
}
protected Set<String> collectComponentKeys() {
Set<String> ids = new HashSet<String>();
ICpConfigurationInfo info = getConfigurationInfo();
collectComponentKeys(ids, info.getGrandChildren(CmsisConstants.COMPONENTS_TAG));
collectComponentKeys(ids, info.getGrandChildren(CmsisConstants.APIS_TAG));
return ids;
}
static protected void collectComponentKeys(Set<String> ids, Collection<? extends ICpItem> children) {
if(children == null || children.isEmpty()) {
return;
}
for(ICpItem child : children) {
if(!(child instanceof ICpComponentInfo)) {
continue;
}
ICpComponentInfo ci = (ICpComponentInfo)child;
String key = ci.getName() + ':' + ci.getAttribute(CmsisConstants.INSTANCES);
if(ci.isVersionFixed()) {
key += ':' + ci.getVersion();
}
ids.add(key);
}
}
@Override
public void reloadPacks() {
collectPacks();
fRtePackCollection.setPackFilterInfo(fModel.getConfigurationInfo().getPackFilterInfo());
update();
}
protected void collectPacks() {
ICpPackCollection allPacks = null;
ICpPackManager pm = CpPlugIn.getPackManager();
if(pm != null) {
allPacks = pm.getInstalledPacks();
}
fRtePackCollection = new RtePackCollection();
if(allPacks != null) {
fRtePackCollection.addCpItem(allPacks);
}
}
@Override
public void setConfigurationInfo(ICpConfigurationInfo info) {
if(info == null) {
clear();
return;
}
fSavedPackFilter = new CpPackFilter(info.createPackFilter());
fCurrentPackFilter = new CpPackFilter(fSavedPackFilter);
fSavedDeviceAttributes = new Attributes(info.getDeviceInfo().attributes());
collectPacks();
fRtePackCollection.setPackFilterInfo(info.getPackFilterInfo());
fModel.setConfigurationInfo(info); // will update used packs
fRtePackCollection.setUsedPacks(getUsedPackInfos());
fSavedComponentKeys = collectComponentKeys(); // initial update
fSavedGpdscFiles = collectGpdscFiles();// initial update
}
@Override
public void updateConfigurationInfo() {
if(getConfigurationInfo() == null) {
return;
}
if(setPackFilter(fCurrentPackFilter)) {
update();
} else {
updateComponentInfos();
}
}
@Override
public void updateComponentInfos() {
fModel.updateComponentInfos();
fRtePackCollection.setUsedPacks(getUsedPackInfos());
}
public void update() {
update(RteConstants.NONE);
}
@Override
public void update(int flags) {
updateComponentInfos();
updatePackFilterInfo();
fModel.update(flags);
fRtePackCollection.setUsedPacks(getUsedPackInfos());
emitRteEvent(RteEvent.CONFIGURATION_MODIFIED, this);
}
@Override
public void commit() {
ICpConfigurationInfo info = fModel.getConfigurationInfo();
if(info != null) {
setSavedFlags(info.getGrandChildren(CmsisConstants.COMPONENTS_TAG));
setSavedFlags(info.getGrandChildren(CmsisConstants.APIS_TAG));
}
if(isGpdscFileListModified()) {
update();
} else {
updateConfigurationInfo();
}
fModel.getComponents().purge();
fRtePackCollection.purge();
fSavedPackFilter = new CpPackFilter(getPackFilter());
fCurrentPackFilter = new CpPackFilter(fSavedPackFilter);
fSavedDeviceAttributes = new Attributes(getDeviceInfo().attributes());
fSavedComponentKeys = collectComponentKeys();
fSavedGpdscFiles = collectGpdscFiles();
fbComponentSelectionModified = false;
fbPackFilterModified = false;
fbDeviceModified = false;
emitRteEvent(RteEvent.CONFIGURATION_COMMITED, this);
}
protected void setSavedFlags(Collection<? extends ICpItem> children) {
;
if(children != null) {
for(ICpItem item : children) {
if(item instanceof ICpComponentInfo) {
ICpComponentInfo ci = (ICpComponentInfo)item;
ci.setSaved(true);
}
}
}
}
@Override
public IRtePackCollection getRtePackCollection() {
return fRtePackCollection;
}
/**
* Returns absolute gpdsc filename associated with component
* @param component {@link IRteComponent}
* @return associated gpdsc file or null if none
*/
protected String getGpdsc(IRteComponent component) {
if(component == null)
return null;
ICpComponent c = component.getActiveCpComponent();
if(c == null)
return null;
if(c.isGenerated()) {
ICpPack pack = c.getPack();
if(pack == null)
return null; // should not happen
return pack.getFileName();
}
ICpGenerator gen = c.getGenerator();
if(gen != null) {
ICpEnvironmentProvider ep = CpPlugIn.getEnvironmentProvider();
return ep.expandString(gen.getGpdsc(), getConfigurationInfo(), true);
}
return null;
}
@Override
public void selectComponent(IRteComponent component, int nInstances) {
if(component == null)
return;
ICpComponent old = component.getActiveCpComponent();
fModel.selectComponent(component, nInstances);
postChangeSelection(component, old);
}
@Override
public void selectActiveVariant(IRteComponentItem item, String variant) {
if(item == null)
return;
ICpComponent old = item.getActiveCpComponent();
item.setActiveVariant(variant);
postChangeSelection(item, old);
}
@Override
public void selectActiveVendor(IRteComponentItem item, String vendor) {
if(item == null)
return;
ICpComponent old = item.getActiveCpComponent();
item.setActiveVendor(vendor);
postChangeSelection(item, old);
}
@Override
public void selectActiveVersion(IRteComponentItem item, String version) {
if(item == null)
return;
ICpComponent old = item.getActiveCpComponent();
item.setActiveVersion(version);
postChangeSelection(item, old);
}
protected void postChangeSelection(IRteComponentItem item, ICpComponent oldComponent) {
if(item instanceof IRteComponent) {
IRteComponent component = (IRteComponent) item;
String genId = component.getGeneratorId();
String oldGenId = oldComponent != null ? oldComponent.getGeneratorId() : null;
if(oldGenId != null && !oldGenId.equals(genId)){
adjustGeneratedSelection(component, oldGenId, false);
}
if(genId != null){
adjustGeneratedSelection(component, genId, component.isSelected());
}
}
updateComponentInfos();
evaluateComponentDependencies();
}
protected void adjustGeneratedSelection(IRteComponent component, String genId, boolean bSelect) {
IRteComponentItem componentRoot = getComponents();
Collection<IRteComponent> componentsToSelect = componentRoot.getGeneratorComponents(genId, null);
if(componentsToSelect == null || componentsToSelect.isEmpty())
return;
int count = bSelect ? 1 : 0;
for(IRteComponent c : componentsToSelect) {
if(c == component)
continue;
c.setSelected(count);
}
}
protected void emitComponentSelectionModified() {
fbComponentSelectionModified = checkIfComponentsModified();
emitRteEvent(RteEvent.COMPONENT_SELECTION_MODIFIED, this);
}
protected void emitPackFilterModified() {
fCurrentPackFilter = fRtePackCollection.createPackFiler();
fbPackFilterModified = !fSavedPackFilter.equals(fCurrentPackFilter);
emitRteEvent(RteEvent.FILTER_MODIFIED, this);
}
@Override
public EEvaluationResult resolveComponentDependencies() {
EEvaluationResult res = fModel.resolveComponentDependencies();
updateComponentInfos();
emitComponentSelectionModified();
return res;
}
@Override
public ICpPackFilter getPackFilter() {
return fModel.getPackFilter();
}
@Override
public boolean setPackFilter(ICpPackFilter filter) {
return fModel.setPackFilter(filter);
}
@Override
public ICpDeviceItem getDevice() {
return fModel.getDevice();
}
@Override
public ICpDeviceInfo getDeviceInfo() {
return fModel.getDeviceInfo();
}
@Override
public void setDeviceInfo(ICpDeviceInfo deviceInfo) {
boolean changed = false;
int updateFlags = RteConstants.NONE;
if(getDeviceInfo() == null) {
changed = true;
} else {
changed = !getDeviceInfo().attributes().equals(deviceInfo.attributes());
if(changed)
updateFlags = RteConstants.COMPONENT_IGNORE_ALL;
}
if(changed) {
fbDeviceModified = !fSavedDeviceAttributes.equals(deviceInfo.attributes());
fModel.setDeviceInfo(deviceInfo);
update(updateFlags);
}
}
@Override
public ICpItem getToolchainInfo() {
return fModel.getToolchainInfo();
}
@Override
public ICpConfigurationInfo getConfigurationInfo() {
return fModel.getConfigurationInfo();
}
@Override
public IRteComponentItem getComponents() {
return fModel.getComponents();
}
@Override
public EEvaluationResult evaluateComponentDependencies() {
EEvaluationResult res = fModel.evaluateComponentDependencies();
emitComponentSelectionModified();
return res;
}
@Override
public EEvaluationResult getEvaluationResult() {
return fModel.getEvaluationResult();
}
@Override
public EEvaluationResult getEvaluationResult(IRteComponentItem item) {
return fModel.getEvaluationResult(item);
}
@Override
public void setEvaluationResult(EEvaluationResult result) {
fModel.setEvaluationResult(result);
}
@Override
public Collection<IRteComponent> getSelectedComponents() {
return fModel.getSelectedComponents();
}
@Override
public Collection<IRteComponent> getUsedComponents() {
return fModel.getUsedComponents();
}
@Override
public Map<String, ICpPackInfo> getUsedPackInfos() {
return fModel.getUsedPackInfos();
}
@Override
public Collection<? extends IRteDependencyItem> getDependencyItems() {
return fModel.getDependencyItems();
}
//@Override
public void updatePackFilterInfo() {
ICpPackFilterInfo packFilterInfo = fRtePackCollection.createPackFilterInfo();
ICpConfigurationInfo confInfo = getConfigurationInfo();
packFilterInfo.setParent(confInfo);
confInfo.replaceChild(packFilterInfo);
}
@Override
public void selectPack(IRtePack pack, boolean select) {
if(pack != null) {
pack.setSelected(select);
IRtePackFamily family = pack.getFamily();
if(family != null) {
family.updateVersionMatchMode();
}
emitPackFilterModified();
}
}
@Override
public void setVesrionMatchMode(IRtePackFamily packFamily, EVersionMatchMode mode) {
if(packFamily != null) {
packFamily.setVersionMatchMode(mode);
emitPackFilterModified();
}
}
@Override
public boolean isUseAllLatestPacks() {
return fRtePackCollection.isUseAllLatestPacks();
}
@Override
public void setUseAllLatestPacks(boolean bUseLatest) {
fRtePackCollection.setUseAllLatestPacks(bUseLatest);
emitPackFilterModified();
}
@Override
public IRteDeviceItem getDevices() {
return fModel.getDevices();
}
@Override
public Map<String, ICpPack> getGeneratedPacks() {
return fModel.getGeneratedPacks();
}
@Override
public ICpPack getGeneratedPack(String gpdsc) {
return fModel.getGeneratedPack(gpdsc);
}
@Override
public boolean isGeneratedPackUsed(String gpdsc) {
return fModel.isGeneratedPackUsed(gpdsc);
}
}