blob: 0097cd5af70f7ffcdfd29ba95c7f5203dd73372b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 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.wst.validation.internal.model;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
import org.eclipse.wst.validation.internal.ContentTypeWrapper;
import org.eclipse.wst.validation.internal.Deserializer;
import org.eclipse.wst.validation.internal.ExtensionConstants;
import org.eclipse.wst.validation.internal.PrefConstants;
import org.eclipse.wst.validation.internal.Serializer;
import org.eclipse.wst.validation.internal.Tracing;
import org.eclipse.wst.validation.internal.ValMessages;
import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
import org.osgi.service.prefs.Preferences;
/**
* A rule that is used to filter out (or in) validation on a resource.
* @author karasiuk
*
*/
public abstract class FilterRule implements IAdaptable {
protected String _pattern;
/**
* Create a rule based on an extension element.
* @param name the extension element, it can be one of projectNature, facet, fileext, file or contentType
* @return null if there is a problem.
*/
public static FilterRule create(String name){
if (ExtensionConstants.Rule.fileext.equals(name))return new FileExt();
if (ExtensionConstants.Rule.projectNature.equals(name))return new ProjectNature();
if (ExtensionConstants.Rule.file.equals(name))return new File();
if (ExtensionConstants.Rule.contentType.equals(name))return new ContentType();
if (ExtensionConstants.Rule.facet.equals(name))return new Facet();
return null;
}
public static FilterRule create(Deserializer des) {
String type = des.getString();
FilterRule fr = create(type);
if (fr != null)fr.load(des);
return fr;
}
public static FilterRule createFile(String pattern, boolean caseSensitive, int type){
File ext = new File();
ext.setData(pattern);
ext.setCaseSensitive(caseSensitive);
ext.setType(type);
return ext;
}
public static FilterRule createFileExt(String pattern, boolean caseSensitive){
FileExt ext = new FileExt();
ext.setData(pattern);
ext.setCaseSensitive(caseSensitive);
return ext;
}
public static FilterRule createFacet(String facetId){
Facet facet = new Facet();
facet.setData(facetId);
return facet;
}
public static FilterRule createProject(String projectNature){
ProjectNature pn = new ProjectNature();
pn.setData(projectNature);
return pn;
}
public static FilterRule createContentType(String contentType, boolean exactMatch){
ContentType ct = new ContentType();
ct.setData(contentType);
ct.setExactMatch(exactMatch);
return ct;
}
public abstract void setData(IConfigurationElement rule);
/**
* Answer true if the rule matches the resource, false if it doesn't, and
* null if the rule does not apply to resources.
*
* @param resource the resource that is being validated.
*/
public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper){
return null;
}
/**
* Answer true if the rule matches the project, false if it doesn't, and null if the
* rule does not apply.
*
* @param project the project that is being validated.
*/
public Boolean matchesProject(IProject project){
return null;
}
public void setData(String data){
_pattern = data;
}
public String toString() {
return getDisplayableType() + ": " + _pattern; //$NON-NLS-1$
}
/** Answer a name of the rule, that can be displayed to a user. */
public String getName(){
return toString();
}
public String getPattern(){
return _pattern;
}
/** Answer the type of rule. */
public abstract String getType();
/** Answer a type that can be displayed to an end user. */
public abstract String getDisplayableType();
public boolean asBoolean(String value, boolean aDefault){
if (value == null)return aDefault;
if (value.equals(ExtensionConstants.True))return true;
if (value.equals(ExtensionConstants.False))return false;
return aDefault;
}
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
return Platform.getAdapterManager().getAdapter(this, adapter);
}
public static class ProjectNature extends FilterRule {
public FilterRule copy() {
ProjectNature rule = new ProjectNature();
rule._pattern = _pattern;
return rule;
}
public void setData(IConfigurationElement rule) {
_pattern = rule.getAttribute(ExtensionConstants.RuleAttrib.id);
}
public String getDisplayableType() {
return ValMessages.RuleProjectNature;
}
public String getType() {
return ExtensionConstants.Rule.projectNature;
}
public Boolean matchesProject(IProject project) {
try {
return project.hasNature(_pattern);
}
catch (CoreException e){
}
return Boolean.FALSE;
}
}
public static class FileExt extends FilterRule {
private boolean _caseSensitive;
public FilterRule copy() {
FileExt rule = new FileExt();
rule._pattern = _pattern;
rule._caseSensitive = _caseSensitive;
return rule;
}
public String getType() {
return ExtensionConstants.Rule.fileext;
}
@Override
public int hashCodeForConfig() {
int h = super.hashCodeForConfig();
if (_caseSensitive)h += 601;
return h;
}
public String getDisplayableType() {
return ValMessages.RuleFileExt;
}
public String getName() {
return toString();
}
public void setData(IConfigurationElement rule) {
_pattern = rule.getAttribute(ExtensionConstants.RuleAttrib.ext);
_caseSensitive = asBoolean(rule.getAttribute(ExtensionConstants.RuleAttrib.caseSensitive), false);
}
public String toString() {
if (_caseSensitive)return NLS.bind(ValMessages.FileExtWithCase, getDisplayableType(), _pattern);
return NLS.bind(ValMessages.FileExtWithoutCase, getDisplayableType(), _pattern);
}
public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper) {
String ext = resource.getFileExtension();
if (_caseSensitive)return _pattern.equals(ext);
return _pattern.equalsIgnoreCase(ext);
}
public boolean isCaseSensitive() {
return _caseSensitive;
}
@Override
public void load(Preferences rid) {
_caseSensitive = rid.getBoolean(PrefConstants.caseSensitive, false);
super.load(rid);
}
@Override
public void save(Preferences rid) {
rid.putBoolean(PrefConstants.caseSensitive, _caseSensitive);
super.save(rid);
}
@Override
protected void load(Deserializer des) {
super.load(des);
_caseSensitive = des.getBoolean();
}
@Override
public void save(Serializer ser) {
super.save(ser);
ser.put(_caseSensitive);
}
public void setCaseSensitive(boolean caseSensitive) {
_caseSensitive = caseSensitive;
}
}
/**
* A rule that is used to filter based on file or folder names.
* @author karasiuk
*
*/
public static class File extends FilterRule {
private boolean _caseSensitive;
private String _patternAsLowercase;
/** One of the FileTypeXX constants. */
private int _type;
public static final int FileTypeFile = 1;
public static final int FileTypeFolder = 2;
public static final int FileTypeFull = 3;
private static final String PortableFileDelim = "/"; //$NON-NLS-1$
public File(){
}
public FilterRule copy() {
File rule = new File();
rule._pattern = _pattern;
rule._patternAsLowercase = _patternAsLowercase;
rule._caseSensitive = _caseSensitive;
rule._type = _type;
return rule;
}
public String getType() {
return ExtensionConstants.Rule.file;
}
@Override
public int hashCodeForConfig() {
int h = super.hashCodeForConfig();
if (_caseSensitive)h += 401;
return h;
}
public String getDisplayableType() {
if (_type == FileTypeFolder)return ValMessages.RuleFolder;
if (_type == FileTypeFull)return ValMessages.RuleFull;
return ValMessages.RuleFile;
}
@Override
public void setData(String pattern) {
if (pattern != null)_patternAsLowercase = pattern.toLowerCase();
else _patternAsLowercase = null;
_pattern = pattern;
}
public void setData(IConfigurationElement rule) {
setData(rule.getAttribute(ExtensionConstants.RuleAttrib.name));
if (_pattern == null)throw new IllegalStateException(ValMessages.ErrPatternAttrib);
_caseSensitive = asBoolean(rule.getAttribute(ExtensionConstants.RuleAttrib.caseSensitive), false);
String type = rule.getAttribute(ExtensionConstants.RuleAttrib.fileType);
if (type == null)throw new IllegalStateException(ValMessages.ErrTypeReq);
if (ExtensionConstants.FileType.file.equals(type))_type = FileTypeFile;
else if (ExtensionConstants.FileType.folder.equals(type)){
_type = FileTypeFolder;
if (!_pattern.endsWith(PortableFileDelim))setData(_pattern + PortableFileDelim);
}
else if (ExtensionConstants.FileType.full.equals(type))_type = FileTypeFull;
else {
Object[] parms = {type, ExtensionConstants.FileType.file, ExtensionConstants.FileType.folder,
ExtensionConstants.FileType.full};
throw new IllegalStateException(NLS.bind(ValMessages.ErrType, parms));
}
}
public String toString() {
if (_caseSensitive)return NLS.bind(ValMessages.FileExtWithCase, getDisplayableType(), _pattern);
return NLS.bind(ValMessages.FileExtWithoutCase, getDisplayableType(), _pattern);
}
public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper) {
String name = null;
switch (_type){
case FileTypeFile:
name = resource.getName();
break;
case FileTypeFolder:
name = resource.getProjectRelativePath().removeLastSegments(1).toString() + PortableFileDelim;
break;
case FileTypeFull:
name = resource.getProjectRelativePath().toPortableString();
break;
}
if (name == null)return Boolean.FALSE;
if (_caseSensitive)return name.startsWith(_pattern);
return name.toLowerCase().startsWith(_patternAsLowercase);
}
@Override
public void load(Preferences rid) {
_caseSensitive = rid.getBoolean(PrefConstants.caseSensitive, false);
_type = rid.getInt(PrefConstants.fileType, -1);
super.load(rid);
}
@Override
public void save(Preferences rid) {
rid.putBoolean(PrefConstants.caseSensitive, _caseSensitive);
rid.putInt(PrefConstants.fileType, _type);
super.save(rid);
}
@Override
protected void load(Deserializer des) {
super.load(des);
_caseSensitive = des.getBoolean();
_type = des.getInt();
}
@Override
public void save(Serializer ser) {
super.save(ser);
ser.put(_caseSensitive);
ser.put(_type);
}
public void setCaseSensitive(boolean caseSensitive) {
_caseSensitive = caseSensitive;
}
public void setType(int type) {
_type = type;
}
}
public static class Facet extends FilterRule {
public FilterRule copy() {
Facet rule = new Facet();
rule._pattern = _pattern;
return rule;
}
public String getType() {
return ExtensionConstants.Rule.facet;
}
public String getDisplayableType() {
return ValMessages.RuleFacet;
}
public void setData(IConfigurationElement rule) {
_pattern = rule.getAttribute(ExtensionConstants.RuleAttrib.id);
}
@Override
public Boolean matchesProject(IProject project) {
try {
return FacetedProjectFramework.hasProjectFacet(project, _pattern);
}
catch (CoreException e){
if (Tracing.isLogging())ValidationPlugin.getPlugin().handleException(e);
}
return Boolean.FALSE;
}
}
public static class ContentType extends FilterRule {
private transient IContentType _type;
private boolean _exactMatch = true;
public FilterRule copy() {
ContentType rule = new ContentType();
rule._pattern = _pattern;
rule._type = _type;
rule._exactMatch = _exactMatch;
return rule;
}
public String getType() {
return ExtensionConstants.Rule.contentType;
}
@Override
public int hashCodeForConfig() {
int h = super.hashCodeForConfig();
if (_exactMatch)h += 301;
return h;
}
public String getDisplayableType() {
return ValMessages.RuleContentType;
}
@Override
public void load(Preferences rid) {
_exactMatch = rid.getBoolean(PrefConstants.exactMatch, true);
super.load(rid);
}
@Override
public void save(Preferences rid) {
rid.putBoolean(PrefConstants.exactMatch, _exactMatch);
super.save(rid);
}
@Override
protected void load(Deserializer des) {
super.load(des);
_exactMatch = des.getBoolean();
}
@Override
public void save(Serializer ser) {
super.save(ser);
ser.put(_exactMatch);
}
public void setData(IConfigurationElement rule) {
setData(rule.getAttribute(ExtensionConstants.RuleAttrib.id));
boolean exactMatch = true;
String exact = rule.getAttribute(ExtensionConstants.RuleAttrib.exactMatch);
if (ExtensionConstants.False.equals(exact)) exactMatch = false;
setExactMatch(exactMatch);
}
@Override
public void setData(String pattern) {
_pattern = pattern;
_type = Platform.getContentTypeManager().getContentType(pattern);
}
public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper) {
if (_type == null)return Boolean.FALSE;
if (resource instanceof IFile) {
IFile file = (IFile) resource;
IContentType ct = contentTypeWrapper.getContentType(file);
if (ct == null)return Boolean.FALSE;
boolean match = false;
if (_exactMatch)match = ct.getId().equals(_type.getId());
else match = ct.isKindOf(_type);
if (match && Tracing.isTraceMatches())
Tracing.log("FilterRule-01: ", toString() + " has matched " + resource); //$NON-NLS-1$ //$NON-NLS-2$
return match;
}
return Boolean.FALSE;
}
/**
* Should the content type match exactly, or should sub types be
* included as well?
*
* @param exactMatch
* If true this rule will only match this specific content
* type. If false this rule will match this content type and
* any of it's sub types.
*/
public void setExactMatch(boolean exactMatch) {
_exactMatch = exactMatch;
}
@Override
public String toString() {
if (_exactMatch)return NLS.bind(ValMessages.ContentTypeExact, getDisplayableType(), _pattern);
return NLS.bind(ValMessages.ContentTypeNotExact, getDisplayableType(), _pattern);
}
}
/** Answer a deep copy of yourself. */
public abstract FilterRule copy();
/**
* Save yourself in the preference file.
* @param rid
*/
public void save(Preferences rid) {
rid.put(PrefConstants.ruleType, getType());
rid.put(PrefConstants.pattern, getPattern());
}
/**
* @param rule
*/
public void load(Preferences rule) {
setData(rule.get(PrefConstants.pattern, null));
}
protected void load(Deserializer des){
setData(des.getString());
}
/**
* Save your settings into the serializer.
* @param ser
*/
public void save(Serializer ser) {
ser.put(getType());
ser.put(getPattern());
}
public int hashCodeForConfig() {
int h = getType().hashCode();
if (_pattern != null)h += _pattern.hashCode();
return h;
}
}