package com.arm.cmsis.pack;
import java.util.Collection;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.PlatformObject;
import com.arm.cmsis.pack.build.IBuildSettings;
import com.arm.cmsis.pack.common.CmsisConstants;
import com.arm.cmsis.pack.data.ICpDeviceProperty;
import com.arm.cmsis.pack.data.ICpExample;
import com.arm.cmsis.pack.data.ICpItem;
import com.arm.cmsis.pack.events.RteEvent;
import com.arm.cmsis.pack.info.ICpConfigurationInfo;
import com.arm.cmsis.pack.info.ICpDeviceInfo;
import com.arm.cmsis.pack.utils.Utils;
/**
* Default implementation of ICpEnvironmentProvider interface as "null object"
*/
public class CpEnvironmentProvider extends PlatformObject implements ICpEnvironmentProvider {
@Override
public String getName() {
return CmsisConstants.EMPTY_STRING;
}
@Override
public void init() {
// default does nothing
}
@Override
public void release() {
// default does nothing
}
@Override
public ICpPackRootProvider getCmsisRootProvider() {
return null; // default has no root provider
}
@Override
public void handle(RteEvent event) {
// default ignores RTE events
}
@Override
public boolean isEnvironmentSupported(String name, EnvironmentContext context) {
if(name == null)
return false;
// default checks only for this environment independently from context
String thisName = getName();
if(thisName == null || thisName.isEmpty())
return false;
return thisName.equals(name);
}
@Override
public boolean isSupported(ICpItem item) {
if(item == null)
return false;
if(item instanceof ICpExample)
return isExampleSupported((ICpExample)item);
// checks if the item is an environment element
if(CmsisConstants.ENVIRONMENT_TAG.equals(item.getTag())) {
// check if environment name is supported
String envName = item.getName();
if(item instanceof ICpDeviceProperty)
return isEnvironmentSupported(envName, EnvironmentContext.DEVICE);
return isEnvironmentSupported(envName, EnvironmentContext.EXAMPLE);
}
return true;
}
/**
* Checks if given example is supported by this provider and can be instantiated.
* @param example ICpExample to check
* @return true if supported
*/
public boolean isExampleSupported(ICpExample example) {
// default checks if the example has an environment section that is supported
if(example == null)
return false;
Collection<? extends ICpItem> envs = example.getGrandChildren(CmsisConstants.PROJECT_TAG);
if (envs == null || envs.isEmpty()) {
return false;
}
for (ICpItem item : envs) {
if(!item.getTag().equals(CmsisConstants.ENVIRONMENT_TAG))
continue;
if(isSupported(item))
return true;
}
return false;
}
@Override
public IAdaptable copyExample(ICpExample example) {
// default calls ICpPackInstaller to copy the example
ICpPackInstaller packInstaller = CpPlugIn.getPackManager().getPackInstaller();
if(packInstaller == null)
return null;
return packInstaller.copyExample(example);
}
@Override
public void adjustBuildSettings(IBuildSettings buildSettings, ICpConfigurationInfo configInfo) {
if(buildSettings == null || configInfo == null)
return;
adjustDeviceBuildSettings(buildSettings, configInfo);
}
@Override
public void adjustInitialBuildSettings(IBuildSettings buildSettings, ICpConfigurationInfo configInfo) {
adjustBuildSettings(buildSettings, configInfo);
}
/**
* Adjusts build settings according to device info
* @param buildSettings IBuildSettings to adjust
* @param deviceInfo ICpDeviceInfo as information source
*/
public void adjustDeviceBuildSettings(IBuildSettings buildSettings, ICpConfigurationInfo configInfo) {
// default adds misc options and pre/postbuild steps if specified
ICpDeviceInfo deviceInfo = configInfo.getDeviceInfo();
if(deviceInfo == null || deviceInfo.getDevice() == null)
return; // only update settings for available device
ICpItem effectiveProperties = deviceInfo.getEffectiveProperties();
if(effectiveProperties == null)
return;
Collection<ICpItem> envs = effectiveProperties.getChildren(CmsisConstants.ENVIRONMENT_TAG);
if(envs == null)
return;
for(ICpItem e : envs) {
if(!isSupported(e))
continue;
Collection<? extends ICpItem> options = e.getChildren();
if(options == null)
continue;
for(ICpItem o : options){
int optionType = getOptionType(o.getTag());
if(optionType == IBuildSettings.UNKNOWN_OPTION)
continue;
String value = o.getText();
if(optionType == IBuildSettings.PRE_BUILD_STEPS || optionType == IBuildSettings.POST_BUILD_STEPS)
value = expandString(value, configInfo, false);
buildSettings.addStringListValue(optionType, value);
}
}
}
/**
* Converts option tag to option type used by build Settings
* @param tag String option type
* @return integer build type
*/
protected int getOptionType(String tag) {
switch(tag){
case IBuildSettings.AMISC_TAG:
return IBuildSettings.RTE_ASMMISC;
case IBuildSettings.CMISC_TAG:
return IBuildSettings.RTE_CMISC;
case IBuildSettings.CPPMISC_TAG:
return IBuildSettings.RTE_CPPMISC;
case IBuildSettings.LMISC_TAG:
return IBuildSettings.RTE_LMISC;
case IBuildSettings.ARMISC_TAG:
return IBuildSettings.RTE_ARMISC;
default:
break;
}
// pre and post build steps in packs are often given with a suffix like preBuild1, prebuild2, etc.
if(tag.startsWith(IBuildSettings.PRE_BUILD_TAG))
return IBuildSettings.PRE_BUILD_STEPS;
else if(tag.startsWith(IBuildSettings.POST_BUILD_TAG))
return IBuildSettings.POST_BUILD_STEPS;
return IBuildSettings.UNKNOWN_OPTION;
}
@Override
public String expandString(String input, ICpConfigurationInfo configInfo, boolean bAsolute) {
// default converts key sequences (http://www.keil.com/pack/doc/CMSIS/Pack/html/pdsc_generators_pg.html)
// to Eclipse variables
if(input == null || input.isEmpty() || configInfo == null)
return input;
int len = input.length();
int lastIndex = len - 1;
StringBuilder output = new StringBuilder(len);
for(int i = 0 ; i < len; i++) {
char ch = input.charAt(i);
if(i < lastIndex && ( ch == '$' || ch == '#' || ch == '@')) {
String key = input.substring(i, i + 2);
String s = bAsolute ? expandToAbsolute(key, configInfo) : expandToVariable(key, configInfo);
if(s != null) {
output.append(s);
i++; // skip key char
continue;
}
}
output.append(ch);
}
return output.toString();
}
public String expandToVariable(String key, ICpConfigurationInfo configInfo) {
switch(key) {
case "$D": //$NON-NLS-1$
case "#D": //$NON-NLS-1$
case "@D": //$NON-NLS-1$
return expandToAbsolute(key, configInfo);
case "$P": //$NON-NLS-1$
return CmsisConstants.PROJECT_ABS_PATH;
case "#P": //$NON-NLS-1$
return CmsisConstants.PROJECT_ABS_PATH + ".project"; //$NON-NLS-1$
case "$S": //$NON-NLS-1$
return CmsisConstants.CMSIS_DFP_VAR_PRJ;
}
return key; // do not expand, can be another variable
}
public String expandToAbsolute(String key, ICpConfigurationInfo configInfo) {
if(key == null || key.length() <2)
return key;
char ch0 = key.charAt(0);
char ch1 = key.charAt(1);
if(ch1 == 'D') {
ICpDeviceInfo di = configInfo.getDeviceInfo();
String fullDeviceName = di.getDeviceName();
if(ch0 == '$')
return Utils.wildCardsToX(fullDeviceName);
String dName = fullDeviceName;
String pName = CmsisConstants.EMPTY_STRING;
int i = fullDeviceName.indexOf(':');
if (i >= 0) {
dName = fullDeviceName.substring(0, i);
pName = fullDeviceName.substring(i + 1);
}
if(ch0 == '#')
return dName;
else if(ch0 == '@')
return pName;
return key;
}
if(ch1 == 'P') {
String pathName = configInfo.getDir(true);
if(ch0 == '#')
pathName += ".project"; //$NON-NLS-1$
return pathName;
}
if(ch1 == 'S' && ch0 == '$') {
return configInfo.getDfpPath();
}
return key;
}
}