/*******************************************************************************
* Copyright (c) 2009,2010 QNX Software Systems
* 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:
* QNX Software Systems (Alena Laskavaia) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.core.param;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.cdt.codan.core.Messages;
import org.eclipse.cdt.codan.internal.core.CharOperation;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* Custom preference for resource scope
*
* @noextend This class is not intended to be extended by clients.
* @since 1.0
*/
public class FileScopeProblemPreference extends AbstractProblemPreference {
/**
* Key for the scope preference
*/
public static final String KEY = "fileScope"; //$NON-NLS-1$
/**
* Exclusion attribute
*/
public static final String EXCLUSION = "exclusion"; //$NON-NLS-1$
/**
* Inclusion attribute
*/
public static final String INCLUSION = "inclusion"; //$NON-NLS-1$
private IResource resource;
private IPath[] inclusion = new IPath[0];
private IPath[] exclusion = new IPath[0];
/**
* Default constructor
*/
public FileScopeProblemPreference() {
setKey(KEY);
setLabel(Messages.FileScopeProblemPreference_Label);
}
public PreferenceType getType() {
return PreferenceType.TYPE_CUSTOM;
}
/**
* Get attribute. Possible keys are EXCUSION and INCLUSION
*
* @param key
* @return class attribute for given key
*/
public IPath[] getAttribute(String key) {
if (key == EXCLUSION)
return exclusion;
if (key == INCLUSION)
return inclusion;
return null;
}
/**
* Set attribute to a value. Possible keys are EXCUSION and INCLUSION
*
* @param key
* @param value
*/
public void setAttribute(String key, IPath[] value) {
if (key == EXCLUSION)
exclusion = value.clone();
if (key == INCLUSION)
inclusion = value.clone();
}
/**
* @return null for workspace, or project of the resource it is applicable
* for
*/
public IProject getProject() {
if (resource != null)
return resource.getProject();
return null;
}
/**
* @return path of the resource it is applicable to
*/
public IPath getPath() {
if (resource != null)
return resource.getFullPath();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
return root.getFullPath();
}
/**
* @param resource
* the resource to set
*/
public void setResource(IResource resource) {
this.resource = resource;
}
/**
* @return the resource for which scope is define. Null if workspace.
*/
public IResource getResource() {
return resource;
}
@Override
public boolean isDefault(){
if (inclusion.length==0 && exclusion.length==0)
return true;
return false;
}
public String exportValue() {
return exportPathList(INCLUSION, inclusion) + "," //$NON-NLS-1$
+ exportPathList(EXCLUSION, exclusion);
}
protected String exportPathList(String key, IPath[] arr) {
String res = key + "=>("; //$NON-NLS-1$
for (int i = 0; i < arr.length; i++) {
if (i != 0)
res += ","; //$NON-NLS-1$
res += escape(arr[i].toPortableString());
}
return res + ")"; //$NON-NLS-1$
}
@Override
public void importValue(StreamTokenizer tokenizer) throws IOException {
List<IPath> inc = importPathList(tokenizer, INCLUSION);
inclusion = inc.toArray(new IPath[inc.size()]);
checkChar(tokenizer, ',');
List<IPath> exc = importPathList(tokenizer, EXCLUSION);
exclusion = exc.toArray(new IPath[exc.size()]);
}
private void checkChar(StreamTokenizer tokenizer, char c) throws IOException {
tokenizer.nextToken();
if (tokenizer.ttype != c)
throw new IllegalArgumentException("Expected " + c); //$NON-NLS-1$
}
private void checkKeyword(StreamTokenizer tokenizer, String keyword) throws IOException {
tokenizer.nextToken();
if (tokenizer.sval == null || !tokenizer.sval.equals(keyword))
throw new IllegalArgumentException("Expected " + keyword); //$NON-NLS-1$
}
protected List<IPath> importPathList(StreamTokenizer tokenizer, String keyword) throws IOException {
checkKeyword(tokenizer, keyword);
checkChar(tokenizer, '=');
checkChar(tokenizer, '>');
ArrayList<IPath> list = new ArrayList<IPath>();
int token;
int index = 0;
try {
checkChar(tokenizer, '(');
token = tokenizer.nextToken();
if (token != ')')
tokenizer.pushBack();
else
return Collections.emptyList();
while (true) {
token = tokenizer.nextToken();
if (tokenizer.sval == null)
throw new IllegalArgumentException();
list.add(new Path(tokenizer.sval));
token = tokenizer.nextToken();
if (token == ')')
break;
tokenizer.pushBack();
checkChar(tokenizer, ',');
index++;
}
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
return list;
}
@Override
public Object getValue() {
return this;
}
@Override
public void setValue(Object value) {
if (this == value)
return;
FileScopeProblemPreference scope = (FileScopeProblemPreference) value;
setAttribute(INCLUSION, scope.getAttribute(INCLUSION));
setAttribute(EXCLUSION, scope.getAttribute(EXCLUSION));
this.resource = scope.getResource();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.codan.core.param.AbstractProblemPreference#clone()
*/
@Override
public Object clone() {
FileScopeProblemPreference scope = (FileScopeProblemPreference) super.clone();
scope.setValue(this);
return scope;
}
/**
* Checks that resource denotated by the given path is in scope (defined by
* exclusion/inclusion settings of this class). In inclusion list is defined
* check first if it belongs to it, returns false if not.
* Then checks if it belongs to exclusion list and return false if it is.
*
* @param path
* - resource path
* @return true is given path is in scope
*/
public boolean isInScope(IPath path) {
//System.err.println("test " + file + " " + exportValue());
if (inclusion.length > 0) {
if (!matchesFilter(path, inclusion))
return false;
}
if (exclusion.length > 0) {
if (matchesFilter(path, exclusion))
return false;
}
return true;
}
/**
* Checks that given path matches on the paths provided as second argument
*
* @param resourcePath - resource path
* @param paths - array of path patterns, for pattern see
* {@link CharOperation#pathMatch}
* @return true if matches with at least one pattern in the array
*/
public boolean matchesFilter(IPath resourcePath, IPath[] paths) {
char[] path = resourcePath.toString().toCharArray();
for (int i = 0, length = paths.length; i < length; i++) {
char[] pattern = paths[i].toString().toCharArray();
if (CharOperation.pathMatch(pattern, path, true, '/')) {
return true;
}
}
return false;
}
}