/*******************************************************************************
* Copyright (c) 2007, 2012 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.cdt.managedbuilder.xlc.ui.properties;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IFolderInfo;
import org.eclipse.cdt.managedbuilder.core.IHoldsOptions;
import org.eclipse.cdt.managedbuilder.core.IManagedProject;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IOptionApplicability;
import org.eclipse.cdt.managedbuilder.xlc.ui.XLCUIPlugin;
import org.eclipse.cdt.managedbuilder.xlc.ui.preferences.PreferenceConstants;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.jface.preference.IPreferenceStore;
/**
* @author rkerimov
*
* This applicability calculator hides/shows options that are specific to the XL compiler versions
*
*/
public class XLCApplicabilityCalculator implements IOptionApplicability
{
private static final String BUNDLE_NAME = "org/eclipse/cdt/managedbuilder/xlc/ui/properties/applicability.properties";
private static final String PROP_NAME_VERSION_ORDER = "xlc.applicability.version.order";
private static final String PROP_VALUE_PLUS = "+";
private static boolean initialized;
private static List versionOrder;
private static Map applicabilityMap;
public XLCApplicabilityCalculator()
{
if (!initialized)
{
Properties props = null;
ClassLoader loader = this.getClass().getClassLoader();
InputStream input = null;
if (loader != null)
input = loader.getResourceAsStream(BUNDLE_NAME);
if (input == null)
input = ClassLoader.getSystemResourceAsStream(BUNDLE_NAME);
try
{
if (input != null)
{
props = new Properties();
props.load(input);
Set entrySet = props.entrySet();
Iterator iterator = entrySet.iterator();
while (iterator.hasNext())
{
Map.Entry entry = (Map.Entry) iterator.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
if (value == null)
value = "";
if (key.equals(PROP_NAME_VERSION_ORDER))
{
versionOrder = new ArrayList();
String[] versions = value.split(",");
if (versions != null)
{
for (int i = 0; i < versions.length; i ++)
{
versionOrder.add(versions[i].trim());
}
}
}
else
{
if (applicabilityMap == null)
applicabilityMap = new HashMap();
List applicList = (List) applicabilityMap.get(key);
if (applicList == null)
{
applicList = new ArrayList();
applicabilityMap.put(key, applicList);
}
boolean hasGreaterOption = false;
//find if ends with + and set as separate option
if (value.endsWith(PROP_VALUE_PLUS))
{
hasGreaterOption = true;
value = value.substring(0, value.length() - PROP_VALUE_PLUS.length());
}
String[] versions = value.split(",");
if (versions != null)
{
for (int i = 0; i < versions.length; i ++)
{
applicList.add(versions[i].trim());
}
}
if (hasGreaterOption)
applicList.add(PROP_VALUE_PLUS);
}
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (input != null)
{
try
{
input.close();
}
catch (IOException e)
{
// ignore
}
}
}
initialized = true;
}
}
private boolean isApplicable(IBuildObject configuration, IHoldsOptions holder, IOption option)
{
// first we check the preference for this project, if it exists
IProject project = null;
if(configuration instanceof IConfiguration)
{
IConfiguration config = (IConfiguration) configuration;
IManagedProject managedProject = config.getManagedProject();
project = (IProject) managedProject.getOwner();
}
else if(configuration instanceof IFolderInfo)
{
IFolderInfo folderInfo = (IFolderInfo) configuration;
IConfiguration config = folderInfo.getParent();
IManagedProject managedProject = config.getManagedProject();
project = (IProject) managedProject.getOwner();
}
if (project == null)
return false;
String currentVersion = null;
try {
currentVersion = project.getPersistentProperty(new QualifiedName("",
PreferenceConstants.P_XLC_COMPILER_VERSION));
} catch (CoreException e) {
e.printStackTrace();
}
if(currentVersion == null)
{
// if the property isn't set, then use the workbench preference
IPreferenceStore prefStore = XLCUIPlugin.getDefault().getPreferenceStore();
currentVersion = prefStore.getString(PreferenceConstants.P_XLC_COMPILER_VERSION);
}
//if applicability list is empty that means all options applicable to all versions
if (applicabilityMap == null)
return true;
//if applicability list for this option is not defined then option has no applicability restrictions
List applicList = (List) applicabilityMap.get(option.getId());
if (applicList == null || applicList.isEmpty())
return true;
//if version is defined in the list - perfect match
if (applicList.contains(currentVersion))
return true;
//if applicability is defined as 'starting from this version and greater', i.e. 'v8.0+',
//then we need to find out if current version is greater than the last valid in the list
String lastOption = (String) applicList.get(applicList.size() - 1);
if (lastOption != null && lastOption.equals(PROP_VALUE_PLUS))
{
//if 'greater than' option is specified but no version order exists, consider config error and return false
if (versionOrder == null)
return false;
//check for the last valid version in applicability list
String validVersion = null;
//start with element before the +
for (int k = applicList.size() - 2; k >= 0; k --)
{
String version = (String) applicList.get(k);
if (versionOrder.contains(version))
{
validVersion = version;
break;
}
}
//if version that applicability starts with doesn't exist - config error
if (validVersion == null)
return false;
//compare if current compiler version is greater than the applicability version
if (versionOrder.indexOf(currentVersion) > versionOrder.indexOf(validVersion))
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IOptionApplicability#isOptionEnabled(org.eclipse.cdt.managedbuilder.core.IBuildObject, org.eclipse.cdt.managedbuilder.core.IHoldsOptions, org.eclipse.cdt.managedbuilder.core.IOption)
*/
@Override
public boolean isOptionEnabled(IBuildObject configuration,
IHoldsOptions holder, IOption option) {
return isApplicable(configuration, holder, option);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IOptionApplicability#isOptionUsedInCommandLine(org.eclipse.cdt.managedbuilder.core.IBuildObject, org.eclipse.cdt.managedbuilder.core.IHoldsOptions, org.eclipse.cdt.managedbuilder.core.IOption)
*/
@Override
public boolean isOptionUsedInCommandLine(IBuildObject configuration,
IHoldsOptions holder, IOption option) {
return isApplicable(configuration, holder, option);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.managedbuilder.core.IOptionApplicability#isOptionVisible(org.eclipse.cdt.managedbuilder.core.IBuildObject, org.eclipse.cdt.managedbuilder.core.IHoldsOptions, org.eclipse.cdt.managedbuilder.core.IOption)
*/
@Override
public boolean isOptionVisible(IBuildObject configuration,
IHoldsOptions holder, IOption option) {
return isApplicable(configuration, holder, option);
}
}