/*******************************************************************************
* 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.build.settings;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import com.arm.cmsis.pack.build.IBuildSettings;
/**
* The class describes an entry defined by com.arm.cmsis.pack.project.ToolchainAdapter extension point
*
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class RteToolChainAdapterInfo {
private static final String ID = "id"; //$NON-NLS-1$
private static final String NAME = "name"; //$NON-NLS-1$
private static final String DESCRIPTION = "Description"; //$NON-NLS-1$
private static final String CLASS = "class"; //$NON-NLS-1$
private static final String TOOLCHAIN_FAMILY = "toolChainFamily"; //$NON-NLS-1$
private Set<String> fAssociations = new HashSet<String>();
private IConfigurationElement fConfigElement;
private String fId;
private String fName;
private String fTcompiler;
private String fDescription;
private String fPlugInId; // originating plug-in ID
private static class NullAdapter implements IRteToolChainAdapter {
static final NullAdapter INSTANCE = new NullAdapter();
@Override
public void setToolChainOptions(IConfiguration configuration, IBuildSettings buildSettings) {
// does nothing
}
@Override
public void setInitialToolChainOptions(IConfiguration configuration, IBuildSettings buildSettings) {
// does nothing
}
@Override
public ILinkerScriptGenerator getLinkerScriptGenerator() {
return null;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public Object getAdapter(Class adapter) {
return null;
}
}
/**
* Constructs info out of IConfigurationElement
* @param element IConfigurationElement
*/
public RteToolChainAdapterInfo(IConfigurationElement element) {
fConfigElement = element;
fId = element.getAttribute(ID);
fName = element.getAttribute(NAME);
fTcompiler = element.getAttribute(TOOLCHAIN_FAMILY);
fDescription = element.getAttribute(DESCRIPTION);
fPlugInId = element.getNamespaceIdentifier();
}
/**
* Returns IRteToolChainAdapter, instantiates it if needed
* @return IRteToolChainAdapter
*/
public synchronized IRteToolChainAdapter getToolChainAdapter(){
IRteToolChainAdapter adapter = null;
try {
adapter = createAdapter();
} catch (CoreException e) {
CCorePlugin.log(e);
}
if(adapter == null){
adapter = NullAdapter.INSTANCE;
}
return adapter;
}
private IRteToolChainAdapter createAdapter() throws CoreException{
Object obj = fConfigElement.createExecutableExtension(CLASS);
if(obj instanceof IRteToolChainAdapter){
return (IRteToolChainAdapter)obj;
}
Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Invalid toolchain adapter class specified"); //$NON-NLS-1$
throw new CoreException(status);
}
/**
* Returns unique toolchain adapter ID
* @return ID string
*/
public String getId() {
return fId;
}
/**
* Returns toolchain adapter name
* @return toolchain adapter name
*/
public String getName() {
return fName;
}
/**
* Returns toolchain family : corresponds to Tcompiler filter attribute in RTE model
* @return toolchain family
*/
public String getFamily() {
return fTcompiler;
}
/**
* Returns toolchain adapter short description
* @return description string
*/
public String getDescription() {
return fDescription;
}
/**
* Addst toolchain association to this adapter
* @param toolChainId toolchain id this adapter
*/
public void addToolChainAssociation(String toolChainId) {
int pos = toolChainId.indexOf('*');
if(pos >=0 ){
if(toolChainId.equals("*")) // actually the same as no limit //$NON-NLS-1$
return;
// translate wildcard to regexp
String regex = ("\\Q" + toolChainId + "\\E").replace("*", "\\E.*\\Q"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
fAssociations.add(regex);
} else {
fAssociations.add(toolChainId);
}
}
/**
*
* @param toolChain IToolChain to match
* @return one of the following (best match is positive and has lower weight)
* <dl>
* <dt>0<dd>adapter does not match the toolchain
* <dt>99<dd>adapter has no associations => generic
* <dt>10...39<dd>exact match of toolchain ID or its super classes ID
* <dt>40...<dd>wildcard match of toolchain ID or its super classes ID
* </dl>
* */
public int matchToolChain(IToolChain toolChain){
if(fAssociations.isEmpty())
return 99;
int result = 10;
// first try exact match
IToolChain tc;
for(tc = toolChain; tc != null; tc = tc.getSuperClass(), result++) {
String id = tc.getId();
if(fAssociations.contains(id))
return result;
}
// perform wildcard match
result = 40;
for(tc = toolChain; tc != null; tc = tc.getSuperClass(), result++) {
String id = tc.getId();
if(matchesToolChainId(id))
return result;
}
return 0;
}
/**
* Performs wildcard match
* @param id toolchain id to match
* @return true if matches
*/
private boolean matchesToolChainId(String id) {
for (String associatedId : fAssociations) {
boolean matches = false;
if(associatedId.indexOf('*') < 0)
matches = id.equals(associatedId);
else
matches = id.matches(associatedId);
if(matches)
return true;
}
return false;
}
/**
* Returns originating plug-in ID
* @return the plug-in ID string
*/
public String getPlugInId() {
return fPlugInId;
}
}