/*
* #!
* Ontopia Vizigator
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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.
* !#
*/
package net.ontopia.topicmaps.viz;
import java.util.Collection;
import java.util.Iterator;
import net.ontopia.topicmaps.core.TopicNameIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.topicmaps.core.index.ClassInstanceIndexIF;
import net.ontopia.topicmaps.core.index.ScopeIndexIF;
import net.ontopia.topicmaps.utils.TypeHierarchyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* INTERNAL: Abstract class which provides access to filtering themes
* out which are not relevant to the user context.
*/
public class BasenameUserThemeFilter extends AbstractUserThemeFilter {
// initialize logging category
static Logger log = LoggerFactory.getLogger(BasenameUserThemeFilter.class.getName());
// members
protected ScopeIndexIF scopeIndex;
protected ClassInstanceIndexIF instanceIndex;
public BasenameUserThemeFilter(TopicMapIF topicMap) {
// super(topicMap);
setTopicMap(topicMap);
}
//
// implementing method from UserThemeFilterIF
//
public void setTopicMap(TopicMapIF topicMap) {
this.topicMap = topicMap;
// initialize useful indexes
scopeIndex = (ScopeIndexIF) topicMap.getIndex("net.ontopia.topicmaps.core.index.ScopeIndexIF");
instanceIndex = (ClassInstanceIndexIF) topicMap.getIndex("net.ontopia.topicmaps.core.index.ClassInstanceIndexIF");
}
/**
* Process theme and find out if it belongs to the user context and
* should therefore be displayed when selecting them. If any of the
* following rules apply the theme should be not displayed.
*
* [Assumption:
* Topic "A" is a theme that scopes a base name of topic "B"]
*
*
* Rule 1: if there exists an association between topic belonging to
* this theme and one or more topics which are related to the
* scoped base names
* OR
* if one or more topics belonging to scoped basename(s)
* is/are of type of the theme
*
* ( "B" is associated with "A" OR
* "B" is an instance of "A" )
*
* Role 2: topic belonging to this theme is used to type association roles
* AND
* one or more topics belonging to with this theme scoped basenames
* are used to type associations in which the
* topic belonging to the theme is playing an association role
*
* ( "A" is the role type in at least one association of type "B" AND
* "B" is an association type )
*
* Role 3: one or more of the topics belonging to the scoped basenames
* is/are used as a scope theme itself/themselves
*
* ( "B" is a theme )
*
* @return boolean: true if this theme should not be displayed
* for user context configuration
*/
public boolean shouldNotBeUsed(TopicIF actTheme) {
boolean usedAsTopicType = false; // (pre) Rule 1A
boolean usedAsAssociationRoleType = false; // (pre) Rule 2
TypeHierarchyUtils hierarchyHelper = new TypeHierarchyUtils();
// --- get base names that use this theme
Collection baseNames = scopeIndex.getTopicNames(actTheme);
//log.info("\n used for scoping " + baseNames.size() + " topic base names.");
// is not used for scoping anywhere?
if (baseNames.size() == 0)
return true;
// (pre) RULE 1A: theme topic is used to type topics
if ( instanceIndex.usedAsTopicType(actTheme) ) {
usedAsTopicType = true;
}
// (pre) RULE 2: theme topic is used to type association roles
if ( instanceIndex.usedAsAssociationRoleType(actTheme) ) {
//log.debug(" *** " + actTheme + " is used for typing association roles ");
usedAsAssociationRoleType = true;
}
// set up number of topics that are checked
int nTotalTopics = baseNames.size();
int nRemainingTopics = nTotalTopics;
// --- iterate through all topics which belong to scoped basenames
Iterator itNames = baseNames.iterator();
while (itNames.hasNext()) {
TopicNameIF baseName = (TopicNameIF) itNames.next();
TopicIF topic = baseName.getTopic();
//log.debug(" * scoped baseName: " + baseName);
boolean typedByTheme = false; // Rule 1A
boolean associatedWithTheme = false; // Rule 1B
boolean usedToTypeAssocs = false; // Rule 2
boolean usedAsTopicNameTheme = false; // Rule 3A
// RULE 1A: topic belonging to scoped basename is of type of theme topic
if ( usedAsTopicType && hierarchyHelper.isInstanceOf(topic, actTheme) ) {
typedByTheme = true;
}
else {
// RULE 1B: check if associated with the topic of this theme
if ( hierarchyHelper.isAssociatedWith(topic, actTheme) ) {
associatedWithTheme = true;
}
else {
// RULE 2: with this theme scoped base name is used to type associations
if ( usedAsAssociationRoleType && instanceIndex.usedAsAssociationType(topic) ) {
usedToTypeAssocs = true;
// FIXME: be more accurate here
// "B" is an association type AND
// "A" is the role type in at least one association of type "B"
}
else {
// RULE 3A: if used in other theme
boolean checkRule3 = false;
if ( scopeIndex.usedAsTopicNameTheme(topic) && checkRule3) {
// usedAsTopicNameTheme = true;
// -- break out of the loop if at least one topic is used as theme
// nRemainingTopics = 0;
// break;
// RULE 3B: check for all topics if they are all used as themes
Iterator itNamesR3 = baseNames.iterator();
int nRemainingTopicsR3 = baseNames.size();
while (itNamesR3.hasNext()) {
TopicNameIF baseNameR3 = (TopicNameIF) itNamesR3.next();
TopicIF topicR3 = baseNameR3.getTopic();
//log.debug(" Check Rule 3 for topic: " + topicR3);
//log.debug(" -> usedToScope: " + scopeIndex.usedAsTopicNameTheme(topicR3));
if ( scopeIndex.usedAsTopicNameTheme(topicR3) ) {
nRemainingTopicsR3--;
} else {
break;
}
}
// theme should not be displayed, if all topics are used for scoping
if (nRemainingTopicsR3 == 0) {
nRemainingTopics = 0;
break;
}
} // if RULE 3A applies
} // if RULE 2 applies
} // if RULE 1B applies
} // if RULE 1A applies
// if rule (1A|1B|2|3A) apply then reduce number of remaining topics
if (associatedWithTheme || typedByTheme || usedToTypeAssocs || usedAsTopicNameTheme)
nRemainingTopics--;
} // while itNames
// if no topics left, theme should NOT be displayed
return (nRemainingTopics == 0);
}
}