/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/*******
** LWCFilter
**
**
*********/
package tufts.vue;
import java.io.*;
import java.util.*;
import tufts.vue.filter.*;
/**
* LWCFilterPanel
*
* This class describes a logical filter that can be applied to a
* set of LWComponents.
*
* A filter can be on or off and contains a list of logical statements
* that describe a condition. If there are more than one conditions listed, a
* global AND (meaning all conditions must be met) or a logical OR (meaning
* (one or any of the conditons should be met) can be specified.
*
* Any object interested in displaying an item, should check to see if
* the filter by the boolean showComponenet( LWComponent) method.
*
* \**/
public class LWCFilter {
static public final String ACTION_HIDE = "Hide";
static public final String ACTION_SHOW = "Show";
static public final String ACTION_SELECT = "Select";
/** condition constants **/
static public final int CONTAINS = 0;
static public final int IS = 1;
static public final int STARTS = 2;
static public final int ENDS = 3;
/** property source types **/
static public final int ANYWHERE = 0;
static public final int LABEL = 1;
static public final int NOTES = 2;
static public final int USERTYPE= 3;
static public final int METADATA = 4;
static public final int USERDATA = 5;
/////////////
// Fields
//////////////
/** a vector of contraints ??? still used ??? **/
LogicalStatement [] mStatements = null;
Vector statements = null;
/** the logical op state **/
boolean mIsAny = false;
/** the filter action **/
private Object mFilterAction = ACTION_SHOW;
/** is the matching inverse of the logical? A logical NOT **/
private boolean mIsLogicalNot = false;
/** is the map filter currenlty on **/
boolean mIsFilterOn = false;
/** LWMap **/
private LWMap mMap = null;
///////////////////
// Constructors
////////////////////
public LWCFilter() {
super();
mStatements = new LogicalStatement[1];
mStatements[0] = new LogicalStatement();
}
/**
* @param Vector - a Vector of FilterStatementEdtiors
**/
public LWCFilter( Vector pEditors) {
this();
if( (pEditors != null) && ( !pEditors.isEmpty() ) ) {
mStatements = new LogicalStatement[ pEditors.size() ];
for( int i=0; i< pEditors.size(); i++) {
FilterStatementEditor fse = (FilterStatementEditor) pEditors.elementAt( i);
mStatements[i] = fse.getStatement();
}
}
}
public LWCFilter( LWMap pMap) {
this();
setMap( pMap);
}
////////////////////
// Methods
///////////////////
/**
* setFilterOn
* Sets the filter to be on or off
* @param boolean true if on; false if off
**/
public void setFilterOn( boolean pIsOn) {
mIsFilterOn = pIsOn;
}
/**
* isFilterOn
* @return true if on; false if off
**/
public boolean isFilterOn() {
return mIsFilterOn;
}
/** @return true if the action of this filter has a persistent effect on the map
* e.g.: SHOW/HIDE are persistent in that items remained in a changed state as long
* as the filter is in effect, where as the SELECT action has no persistent effect:
* it's just a one-time change of the selection */
public boolean hasPersistentAction() {
return mFilterAction != ACTION_SELECT;
}
public void setFilterAction(Object action) {
if (action != ACTION_HIDE && action != ACTION_SHOW && action != ACTION_SELECT)
throw new IllegalArgumentException(this + " illegal filter action: " + action);
mFilterAction = action;
}
public Object getFilterAction() {
return mFilterAction;
}
public void setStatements(Vector statements) {
this.statements = statements;
}
public Vector getStatements() {
return this.statements;
}
public void removeStatements(Key key) {
Vector removeStatements = new Vector();
Iterator i = statements.iterator();
while(i.hasNext()) {
Statement statement = (Statement)i.next();
if(((String)statement.getKey().getKey()).equals(key.getKey().toString()))
removeStatements.add(statement);
}
this.statements.removeAll(removeStatements);
}
/*
* isSelecting
* @return true if filter should select items on apply; false if not
public boolean isSelecting() {
return mFilterAction == ACTION_SELECT;
}
/**
* isFiltering
* @return true iff should hide or filter matches; false if not
public boolean isFiltering() {
return mFilterAction == ACTION_HIDE;
}
/**
* setFiltering
* @param boolean true if should filter; false if not and should select
public void setIsFiltering( boolean pState) {
mIsFiltering = pState;
}
**/
/**
* isLogicalNot
* @return true if filter should be !isMatch; false if normal
**/
public boolean isLogicalNot() {
return mIsLogicalNot;
}
/**
* setLogicalNot
* @param boolean true if filter results should be logical NOT of results.
**/
public void setLogicalNot( boolean pState) {
mIsLogicalNot = pState;
}
/**
* setMap
* @param LWMap = the map that this filter applies to
**/
public void setMap( LWMap pMap) {
mMap = pMap;
}
/**
* getMap
* @return LWMap the map for this filter
**/
public LWMap getMap() {
return mMap;
}
/**
* setIsAny
* @param boolean true if match applies to any match of a logical statement
* false if ALL matches required for match
**/
public void setIsAny( boolean pIsAny) {
mIsAny = pIsAny;
}
public boolean getIsAny() {
return mIsAny;
}
public LogicalStatement createLogicalStatement() {
return new LogicalStatement();
}
/**
* setLogicalStatements
* @param LogicalStatements [] the set of logical statements
**/
public void setLogicalStatements( LogicalStatement [] pArray ) {
mStatements = pArray;
}
/**
* getLogicalStatements
* @return the set of logical statements
**/
public LogicalStatement [] getLogicalStatements() {
return mStatements;
}
/*
*isMatch
*this method checks if the componenent matches complex logic. It is not enabled in current version of VUE.
*@param LWComponent to be checked.
*@return true if matches the criteria
*/
public boolean isMatch( LWComponent pLWC ) {
// if any, we'll assume FALSE
// if ALL, we'll assume TRUE
boolean matched = !mIsAny;
/**
* for(int i=0; i< mStatements.length; i++ ) {
* LogicalStatement ls = mStatements[ i];
* boolean result = ls.isMatch( pLWC);
*
* if( mIsAny && result) {
* // if looking for ANY and MATCH return true
* return true;
* }
* if( (!mIsAny) && (!result) ) {
* // if it's ALL and no match, return false
* return false;
* }
* }
**/
Iterator i = statements.iterator();
while(i.hasNext()) {
Statement statement = (Statement) i.next();
boolean result = matchStatementComponent(statement,pLWC);
if( mIsAny && result) {
// if looking for ANY and MATCH return true
return true;
}
if( (!mIsAny) && (!result) ) {
// if it's ALL and no match, return false
return false;
}
}
return matched;
}
private boolean matchStatementComponent(Statement statement, LWComponent pLWC) {
if(statement.getKey().getKey().toString().equals("Anywhere"))
return matchLabel(statement, pLWC) | matchNotes(statement, pLWC);
else if(statement.getKey().getKey().toString().equals("Label")) {
return matchLabel(statement, pLWC);
} else if(statement.getKey().getKey().toString().equals("Notes")) {
return matchNotes(statement, pLWC);
} else {
return matchFilter(statement,pLWC);
}
}
private boolean matchLabel(Statement statement, LWComponent pLWC) {
Statement labelStatement = new Statement("Label", pLWC.getLabel());
return labelStatement.compare(statement);
}
private boolean matchNotes(Statement statement, LWComponent pLWC) {
Statement notesStatement = new Statement("Label", pLWC.getNotes());
return notesStatement.compare(statement);
}
private boolean matchFilter(Statement statement,LWComponent pLWC) {
return pLWC.getNodeFilter().compare(statement);
}
public String toString() {
return "LWCFilter[" + mFilterAction
+ " on=" + mIsFilterOn
// + " mStatements=" + (mStatements==null?"null":Arrays.asList(mStatements).toString())
+ " statements=" + statements
+ "]";
}
/**
* LogicalStatement
* This class represents a logical statement for a search filter
*
**/
public class LogicalStatement {
/** the value to search for **/
String mValue = "";
/** the condition for the match (equals, start with, etc) **/
int mCondition = CONTAINS;
/** the source type, (Label, Notes, meta data, etc) **/
int mSourceType = ANYWHERE;
/** the sourceID (if any), could be property name **/
String mSourceID = null;
///////////////////
// Constructor
////////////////////
public LogicalStatement() {
super();
}
///////////
// Methods
//////////////
public void setValue( String pValue) {
mValue = pValue;
}
public String getValue() {
return mValue;
}
public void setCondition( int pValue) {
mCondition = pValue;
}
public int getCondition() {
return mCondition;
}
public void setSourceType( int pType) {
mSourceType = pType;
}
public int getSourceType() {
return mSourceType;
}
public void setSourceID( String pID) {
mSourceID = pID;
}
public String getSourceID() {
return mSourceID;
}
/**
* isMatch
* This method determines if the LWC matches the conditions
* of the this statement.
*
* @param LWComponent the component to check
* @returns true if it matches; false if not
**/
public boolean isMatch( LWComponent pLWC) {
boolean state = false;
switch (getSourceType()) {
case ANYWHERE: return matchAnywhere( pLWC);
case LABEL: return matchLabel( pLWC);
case NOTES: return matchNotes( pLWC);
case USERTYPE: return matchUserMapType( pLWC);
case METADATA: return matchMetaData( pLWC);
case USERDATA: return matchUserProperty( pLWC, false);
}
return state;
}
private boolean matchAnywhere( LWComponent pLWC) {
boolean isMatch = false;
if( matchLabel( pLWC) )
return true;
if( matchNotes( pLWC) )
return true;
if( matchUserMapType( pLWC) )
return true;
if( matchMetaData( pLWC) )
return true;
if( matchUserProperty( pLWC, true) )
return true;
return isMatch;
}
private boolean matchLabel( LWComponent pLWC) {
boolean state = false;
String str = pLWC.getLabel();
state = isMatch( str);
return state;
}
private boolean matchNotes( LWComponent pLWC) {
boolean state = false;
String str = pLWC.getNotes();
state = isMatch( str);
return state;
}
public boolean matchMetaData( LWComponent pLWC ) {
boolean state = false;
Resource r = pLWC.getResource();
if( r != null) {
}
return state;
}
public boolean matchUserProperty( LWComponent pLWC, boolean pCheckAll) {
boolean state = false;
UserMapType type = pLWC.getUserMapType();
if( type != null) {
if( pCheckAll ) {
}
else {
}
}
return state;
}
private boolean matchUserMapType( LWComponent pLWC) {
boolean state = false;
return state;
}
/**
* isMathc
* Determines if the passed string meets the statement requirements
* from the getValue and getCondition values of this statement
*
* @returns true if match; false if no match
**/
private boolean isMatch( String pStr) {
if (pStr == null || mValue == null)
return false;
if (DEBUG) debug(" ...checking( "+pStr+" } to value: "+ mValue);
String search = pStr.toLowerCase();
String filter = mValue.toLowerCase();
switch (getCondition()) {
case CONTAINS: return search.indexOf(filter) != -1;
case IS: return search.equals(filter);
case STARTS: return search.startsWith(filter);
case ENDS: return search.endsWith(filter);
}
// should never happen
throw new IllegalStateException(this + " unknown condition " + getCondition());
}
public String toString() {
return "LogicalStatement[Source: "+mSourceType+" condition: "+mCondition+" value: "+mValue + "]";
}
}
private static final boolean DEBUG = false;
protected void debug( String str) {
if (DEBUG) System.out.println(" -> "+str);
}
}