/*
* #!
* 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.awt.Color;
import java.awt.Font;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import net.ontopia.infoset.core.LocatorIF;
import net.ontopia.infoset.impl.basic.URILocator;
import net.ontopia.net.Base64Decoder;
import net.ontopia.net.Base64Encoder;
import net.ontopia.topicmaps.core.AssociationIF;
import net.ontopia.topicmaps.core.AssociationRoleIF;
import net.ontopia.topicmaps.core.OccurrenceIF;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.core.TopicMapIF;
import net.ontopia.utils.OntopiaRuntimeException;
import net.ontopia.utils.StreamUtils;
import com.touchgraph.graphlayout.Node;
/**
* INTERNAL: Stores and manages configuration. The configuration information is
* stored as a topic map.
*/
public class VizTopicMapConfigurationManager extends VizConfigurationManager {
private VizTopicTypePriorityConfigManager priorityManager;
private static final String TYPE_COLOR = BASE + "type-color";
private static final String TOPIC_TYPE_SHAPE = BASE + "topic-type-shape";
private static final String OVERRIDE_RANDOM_COLORS
= BASE + "override-random-colors";
private static final String ASSOC_TYPE_SHAPE = BASE + "assoc-type-shape";
private static final String ASSOCIATION_TYPE_COLOR_AUTOGENERATED
= BASE + "association-type-color-autogenerated";
private static final String TOPIC_TYPE_COLOR_AUTOGENERATED
= BASE + "topic-type-color-autogenerated";
private static final String TYPE_VISIBLE = BASE + "type-visible";
private static final String SHOW_ROLE_HOVER_HELP = BASE
+ "show-role-hover-help";
private static final String ENABLE_MOTION_KILLER = BASE
+ "enable-motion-killer";
private static final String TYPE_ICON_FILENAME = BASE + "type-icon-filename";
private static final String TYPE_LINE_WEIGHT = BASE + "type-line-weight";
private static final String TYPE_SHAPE_PADDING = BASE + "type-shape-padding";
private static final String TYPE_ICON = BASE + "type-icon";
private static final String TYPE_FONT = BASE + "type-font";
private static final String SINGLE_MOUSE_CLICK = BASE + "single-mouse-click";
private static final String LOCALITY_ALGORITHM = BASE + "locality-algorithm";
private static final String MOTION_KILLER_DELAY = BASE +
"motion-killer-delay";
private static final String MAX_TOPIC_NAME_LENGTH = BASE +
"max-topic-name-length";
private static final String DOUBLE_MOUSE_CLICK = BASE + "double-mouse-click";
private static final String START_TOPIC = BASE + "start-topic";
private static final String SUBJECT_INDICATOR = BASE + "subject-indicator";
private static final String SUBJECT = BASE + "subject";
private static final String SOURCE_LOCATOR = BASE + "source-locator";
private static final String TYPE_INSTANCE_TYPE = BASE + "type-instance";
private boolean visibleByDefault = true;
private final Font defaultFont = UIManager.getFont("TextArea.font");
private final Font defaultAssociationFont = new Font(defaultFont.getFamily(),
defaultFont.getStyle(), defaultFont.getSize() - 2);
private TopicIF typeIcon;
// Topics representing configuration properties of topic and association types
private TopicIF typeColor; // Represents the color.
private TopicIF typeVisible; // Represents whether it should be visible.
private TopicIF typeFont; // Represents the font.
private TopicIF typeExcluded; // Represents whether it should be excluded.
// Topics representing configuration properties of topic types.
private TopicIF typeIconFilename; // Represents the icon.
private TopicIF topicTypeShape; // Represents the shape.
private TopicIF typeShapePadding; // Represents the shape padding.
private TopicIF topicTypeColorAutogeneratedTopic;
// Represents the shape padding.
// Topics representing configuration properties of association types.
private TopicIF assocTypeShape; // Represents the shape.
private TopicIF typeLineWeight; // Represents the line weight.
private TopicIF associationTypeColorAutogeneratedTopic;
// Represents the shape padding.
private TopicIF showRoleHoverHelp;
private TopicIF enableMotionKiller;
private TopicIF startTopic;
private TopicIF typeInstanceType;
private Map iconCache;
private Map fontCache;
private Map colourCache;
private ColorAssigner associationTypeColorAssigner;
private ColorAssigner topicTypeColorAssigner;
public static final Color DEFAULT_PANEL_BACKGROUND_COLOUR = new Color(240,
240, 240);
private TopicIF doubleMouseClick;
private TopicIF singleMouseClick;
private TopicIF localityAlgorithm;
private TopicIF motionKillerDelay;
private TopicIF maxTopicNameLength;
public static final int NODE_ORIENTED = 0;
public static final int EDGE_ORIENTED = 1;
public static final int EXPAND_NODE = 0;
public static final int SET_FOCUS_NODE = 1;
public static final int GO_TO_TOPIC = 2;
private static final int DEFAULT_SINGLE_CLICK = EXPAND_NODE;
private static final int DEFAULT_LOCALITY_ALGORITHM = NODE_ORIENTED;
private static final int DEFAULT_KILLER_DELAY = 3;
public static final int DEFAULT_MAX_TOPIC_NAME_LENGTH = 15;
private static final int DEFAULT_DOUBLE_CLICK = SET_FOCUS_NODE;
private TopicIF displayScopedAssociationNames;
private static final String DISPLAY_SCOPED_ASSOC_NAMES = BASE
+ "display-scoped-assoc-names";
private TopicIF scopeFilter;
private TopicIF filterStrictness;
public static final int SHOW_ALL_ASSOCIATION_SCOPES = 0;
public static final int LOOSE_ASSOCIATION_SCOPES = 1;
public static final int STRICT_ASSOCIATION_SCOPES = 2;
private static final String TYPE_EXCLUDED = BASE + "type-excluded";
private static final String SCOPE_FILTER = BASE + "scope-filter";
private static final String FILTER_STRICTNESS = BASE + "filter-strictness";
private static final int DEFAULT_FILTER_SELECTION =
VizTopicMapConfigurationManager.FILTER_IN;
private TopicIF subjectIndicator;
private TopicIF subject;
private TopicIF sourceLocator;
protected static final String NULL_TOPIC = BASE + "null";
protected TopicIF nullTopic;
private TopicIF scopingTopic;
private TopicIF overrideRandomColorsTopic;
public static final int FILTER_DEFAULT = 2;
public static final int FILTER_OUT = 1;
public static final int FILTER_IN = 0;
private static final String SCOPING_TOPIC = BASE + "scoping-topic";
/**
* Constructor initializes the configuration by loading a topic map from the
* URL given in the parameter.
*/
public VizTopicMapConfigurationManager(File tmfile) throws IOException {
super(tmfile);
setupPriorityManager();
}
/**
* Constructor initializes the configuration by loading a topic map from the
* URL given in the parameter.
*/
public VizTopicMapConfigurationManager(String tmurl) throws IOException {
super(tmurl);
setupPriorityManager();
}
/**
* Creates an empty configuration manager where everything is set to default.
*/
public VizTopicMapConfigurationManager() {
super();
setupPriorityManager();
}
protected void init() {
super.init();
startTopic = getTopic(START_TOPIC);
scopingTopic = getTopic(SCOPING_TOPIC);
subjectIndicator = getTopic(SUBJECT_INDICATOR);
subject = getTopic(SUBJECT);
sourceLocator = getTopic(SOURCE_LOCATOR);
typeVisible = getTopic(TYPE_VISIBLE);
typeColor = getTopic(TYPE_COLOR);
topicTypeShape = getTopic(TOPIC_TYPE_SHAPE);
overrideRandomColorsTopic = getTopic(OVERRIDE_RANDOM_COLORS);
assocTypeShape = getTopic(ASSOC_TYPE_SHAPE);
typeIconFilename = getTopic(TYPE_ICON_FILENAME);
typeIcon = getTopic(TYPE_ICON);
typeLineWeight = getTopic(TYPE_LINE_WEIGHT);
typeFont = getTopic(TYPE_FONT);
typeShapePadding = getTopic(TYPE_SHAPE_PADDING);
associationTypeColorAutogeneratedTopic =
getTopic(ASSOCIATION_TYPE_COLOR_AUTOGENERATED);
topicTypeColorAutogeneratedTopic =
getTopic(TOPIC_TYPE_COLOR_AUTOGENERATED);
typeExcluded = getTopic(TYPE_EXCLUDED);
scopeFilter = getTopic(SCOPE_FILTER);
filterStrictness = getTopic(FILTER_STRICTNESS);
singleMouseClick = getTopic(SINGLE_MOUSE_CLICK);
doubleMouseClick = getTopic(DOUBLE_MOUSE_CLICK);
localityAlgorithm = getTopic(LOCALITY_ALGORITHM);
motionKillerDelay = getTopic(MOTION_KILLER_DELAY);
maxTopicNameLength = getTopic(MAX_TOPIC_NAME_LENGTH);
typeInstanceType = getTopic(TYPE_INSTANCE_TYPE, Messages
.getString("Viz.InstanceOf"));
showRoleHoverHelp = getTopic(SHOW_ROLE_HOVER_HELP);
enableMotionKiller = getTopic(ENABLE_MOTION_KILLER);
displayScopedAssociationNames = getTopic(DISPLAY_SCOPED_ASSOC_NAMES);
Node.DEFAULT_TYPE = Node.TYPE_ROUNDRECT;
associationTypeColorAssigner = new ColorAssigner();
topicTypeColorAssigner = new ColorAssigner();
colourCache = new HashMap();
iconCache = new HashMap();
fontCache = new HashMap();
}
public TopicIF getOverrideColorsTopic() {
return overrideRandomColorsTopic;
}
public TopicIF getTopicTypeShapeTopic() {
return topicTypeShape;
}
public TopicIF getAssociationTypeColorAutogeneratedTopic() {
return associationTypeColorAutogeneratedTopic;
}
public TopicIF getTopicTypeColorAutogeneratedTopic() {
return topicTypeColorAutogeneratedTopic;
}
public TopicIF getAssociationTypeShapeTopic() {
return assocTypeShape;
}
public TopicIF getTopicTypeShapePaddingTopic() {
return typeShapePadding;
}
public TopicIF getTopicTypeIconTopic() {
return typeIcon;
}
public TopicIF getTopicTypeFontTopic() {
return typeFont;
}
public TopicIF getTopicTypeColorTopic() {
return typeColor;
}
public TopicIF getAssociationTypeColorTopic() {
return typeColor;
}
// FIXME: Using the same type for topic types and association types is risky,
// as a topic may be both topic type and association type at the same time.
public TopicIF getTypeVisibleTopic() {
return typeVisible;
}
public TopicIF getTopicTypeExcludedTopic() {
return typeExcluded;
}
public TopicIF getAssociationTypeLineWeightTopic() {
return typeLineWeight;
}
public TopicIF getAssociationTypeFontTopic() {
return typeFont;
}
private void setupPriorityManager() {
priorityManager = new VizTopicTypePriorityConfigManager(this);
}
public VizTopicTypePriorityConfigManager getTTPriorityManager() {
return priorityManager;
}
// --- External interface
public Color getAssociationTypeColor(TopicIF type) {
Color c = (Color) colourCache.get(type);
if (getUsesDefault(type, false) && defaultOverrides(false))
c = lookupColor(defaultAssociationType, typeColor);
if (c == null)
c = lookupColor(type, typeColor);
if (c == null && defaultOverrides(false))
c = lookupColor(defaultAssociationType, typeColor);
if (c == null) {
c = associationTypeColorAssigner.getNextColor();
setTypeColor(type, c);
setOccurenceValue(type, getAssociationTypeColorAutogeneratedTopic(),
true);
}
return c;
}
/**
* returns true iff the default type is set to verride autogenerated values.
* @param isTopicType Set to true to check for the association default type,
* and false for the topic default type.
*/
public boolean defaultOverrides(boolean isTopicType) {
return getOccurrenceValue(isTopicType ? defaultType
: defaultAssociationType, getOverrideColorsTopic(), false);
}
/**
* returns true iff the given topic type is set to use default when it doesn't
* its own colour.
* @param type The type to check.
* @param isTopicType
*/
public boolean getUsesDefault(TopicIF type, boolean isTopicType) {
// Types that don't specify whether they use the dafault state do not by
// default.
return getOccurrenceValue(type, isTopicType
? getTopicTypeColorAutogeneratedTopic()
: getAssociationTypeColorAutogeneratedTopic(), false);
}
public Color getTopicTypeColor(TopicIF type) {
Color c = (Color) colourCache.get(type);
if (getUsesDefault(type, true) && defaultOverrides(true))
c = lookupColor(defaultType, typeColor);
if (c == null)
c = lookupColor(type, typeColor);
if (c == null && defaultOverrides(true))
c = lookupColor(defaultType, typeColor);
if (c == null) {
c = topicTypeColorAssigner.getNextColor();
setTypeColor(type, c);
setOccurenceValue(type, getTopicTypeColorAutogeneratedTopic(), true);
}
return c;
}
public int getTopicTypeShape(TopicIF topictype) {
return getOccurrenceValue(topictype, topicTypeShape,
getOccurrenceValue(defaultType, topicTypeShape, Node.DEFAULT_TYPE));
}
public boolean hasOccurrence(TopicIF topictype, TopicIF type) {
TopicIF cfgtopic = getConfigTopic(topictype);
return cfgtopic != null && getOccurrence(cfgtopic, type) != null;
}
public Font getDefaultFont() {
return defaultFont;
}
public void setTypeColor(TopicIF type, Color c) {
setColor(type, typeColor, c);
colourCache.put(type, c);
}
//-----------------------------------------------
/**
* Sets the colour of a given 'type' and updates 'view' accordingly.
* If the type is defaultType/defaultTopicType, all topic/association types
* that have no explicit colour setting are updated with this colour.
*/
public void setTypeColor(TopicIF type, Color c, TopicMapView view) {
setTypeColor(type, c);
setOccurenceValue(type,
getTopicTypeColorAutogeneratedTopic(), false);
setOccurenceValue(type,
getAssociationTypeColorAutogeneratedTopic(), false);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
boolean hasColor = hasOccurrence(currentType,
getTopicTypeColorTopic());
boolean isAutogenerated = getOccurrenceValue(currentType,
getTopicTypeColorAutogeneratedTopic(), false);
boolean defaultOverrules = getOccurrenceValue(type,
getOverrideColorsTopic(), false);
// If the type doesn't have an explicicly defined color yet:
if (!hasColor || isAutogenerated && defaultOverrules) {
// Update it in view with the new default color.
if (currentType == null) // Untyped topic
removeOccurrence(untypedTopic,
getTopicTypeColorTopic());
else
removeOccurrence(currentType,
getTopicTypeColorTopic());
view.setTypeColor(currentType, c);
}
}
} else if (type == defaultAssociationType) {
// For each association type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
boolean hasColor = hasOccurrence(currentType,
getAssociationTypeColorTopic());
boolean isAutogenerated = getOccurrenceValue(currentType,
getAssociationTypeColorAutogeneratedTopic(), false);
boolean defaultOverrules = getOccurrenceValue(type,
getOverrideColorsTopic(), false);
// If the type doesn't have a defined color yet:
if (!hasColor || isAutogenerated && defaultOverrules) {
// Update it in view with the new default color.
removeOccurrence(currentType,
getAssociationTypeColorTopic());
view.setTypeColor(currentType, c);
}
}
} else
view.setTypeColor(type, c);
}
/**
* Sets the color of a given topic/association 'type' to the default value
* and updates 'view' accordingly.
*/
public void setColorToDefault(TopicIF type, boolean topicType,
TopicMapView view) {
removeOccurence(type, topicType ? getTopicTypeColorTopic()
: getAssociationTypeColorTopic());
if (topicType)
view.setTypeColor(type,
getTopicTypeColor(defaultType));
else
view.setTypeColor(type,
getAssociationTypeColor(defaultAssociationType));
}
/**
* Sets the given topic 'type' be either filtered in, filtered out or to
* use the filter setting of the default type.
* For defaultType, updates all types with no explicit setting.
* Updates view accordingly.
*/
public void setTypeVisibility(TopicIF type, int visibility,
TopicMapView view) {
// Only set configuration for default type itself.
setTypeVisible(type, visibility);
boolean visible =
visibility == VizTopicMapConfigurationManager.FILTER_IN ||
(visibility == VizTopicMapConfigurationManager
.FILTER_DEFAULT &&
isTopicTypeVisible(defaultType));
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// FIXME: Added this code to avoid a NullPointerException, which should,
// never occur, but did occur after filtering in the topic type Opera
// in the Opera topic map and then filtering out Default type.
// Would be good to find out why it occurred, as this is a possible
// source of wrong filtering.
if (currentType == null)
continue;
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTypeVisibleTopic())) {
// Update it in view with the new default filter setting.
view.setTopicTypeVisible(currentType,
visibility == VizTopicMapConfigurationManager
.FILTER_IN);
}
}
} else {
view.setTopicTypeVisible(type, visible);
}
// Having made the appropriate changes to the filtering configuration, now
// add any nodes and edges within locality's reach that are filtered in.
if (visible)
view.loadNodesInLocality(view.getFocusNode(), true, false);
}
/**
* Sets the given association 'type' be either filtered in, filtered out or to
* use the filter setting of the default type.
* For defaultAssociationType, updates all types with no explicit setting.
* Updates view accordingly.
*/
public void setAssociationTypeVisible(TopicIF type, int visibility,
TopicMapView view) {
setTypeVisible(type, visibility);
boolean visible =
visibility == VizTopicMapConfigurationManager.FILTER_IN ||
(visibility == VizTopicMapConfigurationManager.FILTER_DEFAULT &&
isTopicTypeVisible(defaultAssociationType));
if (type == defaultAssociationType) {
// For each association type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If visibility hasn't been set for this type yet:
if (!hasOccurrence(currentType,
getTypeVisibleTopic())) {
// Update it in view with the new default filter setting.
view.setAssociationTypeVisible(currentType,
visibility == VizTopicMapConfigurationManager.FILTER_IN);
}
}
} else {
view.setAssociationTypeVisible(type, visible);
}
// Having made the appropriate changes to the filtering configuration, now
// add any nodes and edges within locality's reach that are filtered in.
if (visible)
view.loadNodesInLocality(view.getFocusNode(), true, false);
}
// FIXME: SHOULD BECOME REDUNDANT. THEN REMOVE.
/**
* Sets the given topic 'type' to be visible and updates 'view' accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setTypeVisible(TopicIF type, boolean visible, TopicMapView view) {
// Only set configuration for default type itself.
setTypeVisible(type, visible);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTypeVisibleTopic())) {
// Update it in view with the new default filter setting.
view.setTopicTypeVisible(currentType, visible);
}
}
} else
view.setTopicTypeVisible(type, visible);
if (visible)
view.loadNodesInLocality(view.getFocusNode(), true, false);
}
// FIXME: TO BECOME REDUNDANT. THEN REMOVE.
/**
* Sets the given association 'type' to be visible and updates 'view'
* accordingly.
* For defaultAssociationType, updates all types with no explicit setting.
*/
public void setAssociationTypeVisible(TopicIF type, boolean visible,
TopicMapView view) {
setTypeVisible(type, visible);
if (type == defaultAssociationType) {
// For each association type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If visibility hasn't been set for this type yet:
if (!hasOccurrence(currentType,
getTypeVisibleTopic())) {
// Update it in view with the new default filter setting.
view.setAssociationTypeVisible(currentType, visible);
}
}
} else
view.setAssociationTypeVisible(type, visible);
}
/**
* Sets the shape of the given topic 'type' and updates 'view' accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setTopicTypeShape(TopicIF type, int i, TopicMapView view) {
setTopicTypeShape(type, i);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTopicTypeShapeTopic()))
// Update it in view with the new default shape.
view.setTopicTypeShape(currentType, i);
}
} else if (i == TypesConfigFrame.UNDEFINED_NODE_SHAPE) {
removeOccurence(type, getTopicTypeShapeTopic());
view.setTopicTypeShape(type,
getTopicTypeShape(defaultType));
} else
view.setTopicTypeShape(type, i);
}
/**
* Sets the shape of the given association 'type' and updates 'view'
* accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setAssociationTypeShape(TopicIF type, int i, TopicMapView view) {
setAssociationTypeShape(type, i);
if (type == defaultAssociationType) {
// For each topic type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getAssociationTypeShapeTopic()))
// Update it in view with the new default shape.
view.setAssociationTypeShape(currentType, i);
}
} else if (i == TypesConfigFrame.UNDEFINED_EDGE_SHAPE) {
removeOccurence(type, getAssociationTypeShapeTopic());
view.setAssociationTypeShape(type,
getAssociationTypeShape(defaultAssociationType));
} else
view.setAssociationTypeShape(type, i);
}
/**
* Sets the font of a given topic/association 'type' to the default value
* and updates 'view' accordingly.
*/
public void setFontToDefault(TopicIF type, boolean topicType,
TopicMapView view) {
removeOccurence(type, topicType ? getTopicTypeFontTopic()
: getAssociationTypeFontTopic());
if (topicType)
view.setTypeFont(type,
getTypeFont(defaultType));
else
view.setTypeFont(type,
getTypeFont(defaultAssociationType));
}
/**
* Sets the font of the given topic/association 'type' and updates 'view'
* accordingly. For defaultType/defaultAssociationType, updates all types
* with no explicit setting.
*/
public void setTypeFont(TopicIF type, Font font, TopicMapView view) {
setTypeFont(type, font);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined font yet:
if (!hasOccurrence(currentType,
getTopicTypeFontTopic()))
// Update it in view with the new default font.
view.setTypeFont(currentType, font);
}
} else if (type == defaultAssociationType) {
// For each association type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined font yet:
if (!hasOccurrence(currentType,
getAssociationTypeFontTopic()))
// Update it in view with the new default font.
view.setTypeFont(currentType, font);
}
} else
view.setTypeFont(type, font);
}
/**
* Sets the line weight of the given association 'type' and updates 'view'
* accordingly.
* For defaultAssociationType, updates all types with no explicit setting.
*/
public void setAssociationTypeLineWeight(TopicIF type, int i,
TopicMapView view) {
setTypeLineWeight(type, i);
if (type == defaultAssociationType) {
// For each topic type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getAssociationTypeLineWeightTopic()))
// Update it in view with the new default shape.
view.setAssociationTypeLineWeight(currentType, i);
}
} else if (i == TypesConfigFrame.UNDEFINED_EDGE_SHAPE_WEIGHT) {
removeOccurence(type,
getAssociationTypeLineWeightTopic());
view.setAssociationTypeLineWeight(type,
getAssociationTypeLineWeight(defaultType));
} else
view.setAssociationTypeLineWeight(type, i);
}
/**
* Sets the shape padding of the given topic 'type' and updates 'view'
* accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setTopicTypeShapePadding(TopicIF type, int i, TopicMapView view) {
setTopicTypeShapePadding(type, i);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTopicTypeShapePaddingTopic()))
// Update it in view with the new default shape.
view.setTopicTypeShapePadding(currentType, i);
}
} else if (i == TypesConfigFrame.UNDEFINED_NODE_SHAPE_PADDING) {
removeOccurence(type, getTopicTypeShapePaddingTopic());
view.setTopicTypeShapePadding(type,
getTopicTypeShape(defaultType));
} else
view.setTopicTypeShapePadding(type, i);
}
/**
* Sets the name of the icon file (optional) of the given topic 'type' and
* updates 'view' accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setTypeIconFilename(TopicIF type, String string,
TopicMapView view) {
setTypeIconFilename(type, string);
Icon icon = getTypeIcon(type);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTopicTypeIconTopic()))
// Update it in view with the new default shape.
view.setTypeIcon(currentType, icon);
}
} else if (type == defaultAssociationType) {
// For each topic type
Iterator typesIt = view.getAssociationTypes().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTopicTypeIconTopic()))
// Update it in view with the new default shape.
view.setTypeIcon(currentType, icon);
}
} else if (string == null) {
removeOccurence(type, getTopicTypeIconTopic());
view.setTypeIcon(type,
getTypeIcon(defaultType));
} else
view.setTypeIcon(type, icon);
}
/**
* Sets the given topic 'type' to be included and updates 'view' accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setTypeIncluded(TopicIF type, TopicMapView view) {
setTypeIncluded(type);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTopicTypeExcludedTopic()))
// Update it in view with the new default shape.
view.setTopicTypeExcluded(currentType, false);
}
} else
view.setTopicTypeExcluded(type, false);
}
/**
* Sets the given topic 'type' to be excluded and updates 'view' accordingly.
* For defaultType, updates all types with no explicit setting.
*/
public void setTypeExcluded(TopicIF type, TopicMapView view) {
setTypeExcluded(type);
if (type == defaultType) {
// For each topic type
Iterator typesIt = view.getAllTopicTypesWithNull().iterator();
while (typesIt.hasNext()) {
TopicIF currentType = (TopicIF)typesIt.next();
// If the type doesn't have a defined shape yet:
if (!hasOccurrence(currentType,
getTopicTypeExcludedTopic()))
// Update it in view with the new default shape.
view.setTopicTypeExcluded(currentType, true);
}
} else
view.setTopicTypeExcluded(type, true);
}
// ----------------------
public void setTopicTypeShape(TopicIF type, int i) {
setOccurrenceValue(type, topicTypeShape, i);
}
public void setAssociationTypeShape(TopicIF type, int i) {
setOccurrenceValue(type, assocTypeShape, i);
}
public void setTypeLineWeight(TopicIF type, int i) {
setOccurrenceValue(type, typeLineWeight, i);
}
public void setTopicTypeShapePadding(TopicIF type, int i) {
setOccurrenceValue(type, typeShapePadding, i);
}
public void setTypeVisible(TopicIF type, int visibility) {
if (visibility == VizTopicMapConfigurationManager.FILTER_DEFAULT) {
if (typeVisible == defaultAssociationType || typeVisible == defaultType)
return;
removeOccurence(type, typeVisible);
} else
setOccurenceValue(type, typeVisible,
visibility == VizTopicMapConfigurationManager.FILTER_IN);
}
// FIXME: THIS METHOD SHOULD BECOME REDUNDANT. REMOVE IT THEN.
public void setTypeVisible(TopicIF type, boolean visible) {
setOccurenceValue(type, typeVisible, visible);
}
public boolean isAssociationTypeVisible(TopicIF assoctype) {
return lookupVisible(assoctype, typeVisible, defaultAssociationType);
}
public boolean isTopicTypeVisible(TopicIF assoctype) {
return lookupVisible(assoctype, typeVisible, defaultType);
}
public boolean lookupVisible(TopicIF type, TopicIF occtype, TopicIF defType) {
TopicIF cfgtopic = getConfigTopic(type);
OccurrenceIF occ = getOccurrence(cfgtopic, occtype);
if (occ == null || occ.getValue() == null) {
cfgtopic = getConfigTopic(defType);
occ = getOccurrence(cfgtopic, occtype);
}
if (occ == null || occ.getValue() == null)
return visibleByDefault;
return occ.getValue().equalsIgnoreCase("true");
}
public boolean isVisible(TopicIF topic) {
Iterator it = topic.getTypes().iterator();
if (!it.hasNext()) // no types
return isTopicTypeVisible(null);
while (it.hasNext()) {
TopicIF type = (TopicIF) it.next();
if (!isTopicTypeVisible(type))
return false;
}
return true;
}
public boolean isVisible(AssociationIF assoc) {
// Only check the visibility of the association
// The visibility of the roles is taken care of in #assertNode()
return isAssociationTypeVisible(assoc.getType()) &&
matchesFilter(assoc.getScope());
}
/**
* Checks if a given scope matches the association scope filter.
* See matchScope(scope, filter) for details.
* @param scope The scope to check for matching.
* @return true iff scope matches the association scope filter.
*/
public boolean matchesFilter(Collection scope) {
Collection filter = getAssociationScopeFilter();
return matchesFilter(scope, filter);
}
/**
* Checks if a given scope (collection of topics) matches a given filter
* (another collection of topics).
* @param scope The scope to match with the filter.
* @param filter The filter for the scope to be matched with.
* @return true iff scope matches filter. The scope either has to contain one,
* all or none of the topics in filter,
* depending on getAssociationFilterTightness().
*/
public boolean matchesFilter(Collection scope, Collection filter) {
// An empty scope matches all filters..
if (scope.isEmpty())
return true;
// An emtpty filter is matched by all scopes.
if (filter.isEmpty())
return true;
int associationFilterStrictness = getAssociationScopeFilterStrictness();
Iterator scopeIt = scope.iterator();
switch (associationFilterStrictness) {
case SHOW_ALL_ASSOCIATION_SCOPES:
// No filter: Show all associations (regardless of scope).
return true;
case LOOSE_ASSOCIATION_SCOPES:
// Show associations with scope matching one+ topic in the filter.
while (scopeIt.hasNext())
if (filter.contains(getConfigTopic((TopicIF)scopeIt.next())))
return true;
return false;
case STRICT_ASSOCIATION_SCOPES:
// Show associaitons with scope matching all topics in the filter.
int filterMatches = 0;
while (scopeIt.hasNext())
if (filter.contains(getConfigTopic((TopicIF)scopeIt.next())))
filterMatches++;
return filterMatches == filter.size();
default: // SHOW_ALL_ASSOCIATION_SCOPES
// No filter: Show all associations (regardless of scope).
return true;
}
}
public boolean isVisible(AssociationRoleIF role) {
// A role is only visible if it is not part of an optimized
// association, and the association object it is part of
// is itself visible. The visibility of the roles is taken
// care of in #assertNode()
if (role.getAssociation().getRoles().size() == 2)
return false;
return isVisible(role.getAssociation());
}
/**
* Finds the color for this association or topic type that is stored in the
* topic map. Returns null if no color is stored in the topic map.
*/
public Color lookupColor(TopicIF type, TopicIF occtype) {
String value = getOccurrenceValue(type, occtype);
if (value == null)
return null;
return parseColor(value);
}
// --- Internal
/**
* Sets the color for this association or topic type in the topic map.
*/
private void setColor(TopicIF type, TopicIF occtype, Color c) {
setOccurenceValue(type, occtype, c.getRed() + " " + c.getGreen() + " "
+ c.getBlue());
}
/**
* Constructs a Color instance from RGB values that are delimited within a
* string.
*/
private Color parseColor(String value) {
try {
StringTokenizer strtok = new StringTokenizer(value);
int red = Integer.parseInt(strtok.nextToken());
int green = Integer.parseInt(strtok.nextToken());
int blue = Integer.parseInt(strtok.nextToken());
return new Color(red, green, blue);
} catch (Exception e) {
throw new OntopiaRuntimeException(Messages.getString(
"Viz.ColourParseError", value));
}
}
// --- Color assigner
/**
* Helper class which can semi-randomly provide colors.
*/
private class ColorAssigner {
private int previous;
private Color[] colors;
private ColorAssigner() {
previous = -1;
colors = new Color[22];
colors[0] = new Color(116, 10, 57);
colors[1] = new Color(219, 1, 99);
colors[2] = new Color(245, 157, 205);
colors[3] = new Color(121, 9, 125);
colors[4] = new Color(247, 21, 255);
colors[5] = new Color(245, 179, 241);
colors[6] = new Color(9, 20, 121);
colors[7] = new Color(1, 34, 233);
colors[8] = new Color(92, 114, 250);
colors[9] = new Color(9, 125, 129);
colors[10] = new Color(17, 235, 255);
colors[11] = new Color(153, 245, 242);
colors[12] = new Color(161, 245, 165);
colors[12] = new Color(0, 238, 22);
colors[13] = new Color(11, 85, 14);
colors[14] = new Color(229, 255, 5);
colors[15] = new Color(250, 248, 150);
colors[16] = new Color(134, 55, 8);
colors[17] = new Color(255, 71, 21);
colors[18] = new Color(246, 164, 142);
colors[19] = new Color(10, 106, 66);
colors[20] = new Color(11, 22, 89);
colors[21] = Color.darkGray;
}
public Color getNextColor() {
if (previous < colors.length - 1)
previous++;
return colors[previous];
}
}
/**
* INTERNAL: Finds the start topic in the given topic map, and returns it.
*/
public TopicIF getStartTopic(TopicMapIF graphtm) {
return getTopicFromReference(graphtm, startTopic);
}
/**
* INTERNAL: Finds the scoping topic in the given topic map, and returns it.
*/
public TopicIF getScopingTopic(TopicMapIF graphtm) {
return getTopicFromReference(graphtm, scopingTopic);
}
/**
* INTERNAL: Finds the scoping topic in the given topic map, and returns it.
*/
public TopicIF getScopingTopicHolder() {
return scopingTopic;
}
private TopicIF getTopicFromReference(TopicMapIF graphtm, TopicIF reference) {
// See #setTopicReference()
// for full details how the start topic is referenced.
String base = graphtm.getStore().getBaseAddress().getAddress();
Iterator occurs = reference.getOccurrences().iterator();
if (occurs.hasNext()) {
OccurrenceIF occurrence = (OccurrenceIF) occurs.next();
TopicIF occType = occurrence.getType();
if (occType == null) {
// This is just here for backwards compatability
LocatorIF loc = occurrence.getLocator();
TopicIF topic = (TopicIF) graphtm.getObjectByItemIdentifier(loc);
// convert to new form
if (topic != null)
setStartTopic(topic);
return topic;
} else if (subjectIndicator.equals(occType)) {
LocatorIF locator = occurrence.getLocator();
if (locator == null) {
String data = occurrence.getValue();
try {
locator = new URILocator(base + data);
} catch (MalformedURLException e) {
// Ignore any errors
}
}
return graphtm.getTopicBySubjectIdentifier(locator);
} else if (subject.equals(occType)) {
LocatorIF locator = occurrence.getLocator();
return graphtm.getTopicBySubjectLocator(locator);
} else if (sourceLocator.equals(occType)) {
LocatorIF locator = occurrence.getLocator();
if (locator == null) {
String data = occurrence.getValue();
try {
locator = new URILocator(base + data);
} catch (MalformedURLException e) {
// Ignore any errors
}
}
return (TopicIF) graphtm.getObjectByItemIdentifier(locator);
}
}
return null;
}
/**
* Sets the start topic of the vizualization. We use the srclocator stored in
* an occurrence as not all topics have a subjind.
*/
public void setStartTopic(TopicIF extstart) {
setTopicReference(startTopic, extstart, extstart.getTopicMap().getStore()
.getBaseAddress().getAddress());
}
protected void setTopicReference(TopicIF topic, TopicIF extstart,
String base) {
clearTopic(topic); // removes the occurrences recording the srclocs
for (Iterator iter = extstart.getSubjectIdentifiers().iterator(); iter
.hasNext();) {
LocatorIF locator = (LocatorIF) iter.next();
if (locator.getAddress().startsWith(base))
builder.makeOccurrence(topic, subjectIndicator, locator.getAddress()
.substring(base.length()));
else
builder.makeOccurrence(topic, subjectIndicator, locator);
return;
}
for (Iterator iter = extstart.getSubjectLocators().iterator(); iter
.hasNext();) {
LocatorIF locator = (LocatorIF) iter.next();
if (locator.getAddress().startsWith(base))
builder.makeOccurrence(topic, subject, locator.getAddress()
.substring(base.length()));
else
builder.makeOccurrence(topic, subject, locator);
return;
}
for (Iterator iter = extstart.getItemIdentifiers().iterator(); iter
.hasNext();) {
LocatorIF locator = (LocatorIF) iter.next();
if (locator.getAddress().startsWith(base))
builder.makeOccurrence(topic, sourceLocator, locator.getAddress()
.substring(base.length()));
else
builder.makeOccurrence(topic, sourceLocator, locator);
return;
}
}
/** Clear the start topic if it was set. */
public void clearTopic(TopicIF aTopic) {
if (!aTopic.getOccurrences().isEmpty()) {
Iterator it = new ArrayList(aTopic.getOccurrences()).iterator();
while (it.hasNext()) {
OccurrenceIF occur = (OccurrenceIF) it.next();
occur.remove();
}
}
}
public TopicIF getTypeInstanceType() {
return typeInstanceType;
}
public int getTypeVisibility(TopicIF selectedType) {
String visibility = getOccurrenceValue(selectedType, typeVisible);
if (visibility == null) {
return selectedType == defaultAssociationType ||
selectedType == defaultType ?
DEFAULT_FILTER_SELECTION :
VizTopicMapConfigurationManager.FILTER_DEFAULT;
}
if (visibility.equals("true"))
return VizTopicMapConfigurationManager.FILTER_IN;
if (visibility.equals("false"))
return VizTopicMapConfigurationManager.FILTER_OUT;
// The following should never happen, and is an error in the configuration.
throw new OntopiaRuntimeException("Error in Vizigator configuration. " +
"Filter setting should always be 'true' or 'false', but was'" +
visibility + "'");
}
public int getAssociationTypeShape(TopicIF selectedType) {
return getOccurrenceValue(selectedType, assocTypeShape,
getOccurrenceValue(defaultType, assocTypeShape,
TMRoleEdge.DEFAULT_SHAPE));
}
public int getAssociationTypeLineWeight(TopicIF selectedType) {
return getOccurrenceValue(selectedType, typeLineWeight,
getOccurrenceValue(defaultAssociationType, typeLineWeight,
TMRoleEdge.DEFAULT_LINE_WEIGHT));
}
public int getTopicTypeShapePadding(TopicIF selectedType) {
return getOccurrenceValue(selectedType, typeShapePadding,
getOccurrenceValue(defaultType, typeShapePadding,
TMTopicNode.DEFAULT_SHAPE_PADDING));
}
public String getTypeIconFilename(TopicIF type) {
return getOccurrenceValue(type, typeIconFilename);
}
public Icon getTypeIcon(TopicIF type) {
return lookupIcon(type, typeIconFilename, typeIcon);
}
public Font getTypeFont(TopicIF type) {
return getTypeFont(type, getTypeFont(defaultType, getDefaultFont()));
}
public Font getAssociationTypeFont(TopicIF type) {
return getTypeFont(type, getDefaultAssociationFont());
}
private Font getDefaultAssociationFont() {
return defaultAssociationFont;
}
private Font getTypeFont(TopicIF type, Font df) {
String result = getOccurrenceValue(type, typeFont);
if (result == null) {
if (type == defaultType)
setTypeFont(defaultType, df);
if (type == defaultAssociationType)
setTypeFont(defaultAssociationType, df);
return df;
}
return parseFont(result);
}
public void setTypeFont(TopicIF type, Font font) {
setOccurenceValue(type, typeFont, serializeFont(font));
}
private String serializeFont(Font font) {
// Fonts are serialized to the form:
// "<family name>-<style>-<size>"
StringBuilder buffer = new StringBuilder();
buffer.append(font.getFamily());
buffer.append("-");
buffer.append(font.getStyle());
buffer.append("-");
buffer.append(font.getSize());
String result = buffer.toString();
fontCache.put(result, font);
return result;
}
public Font parseFont(String fontString) {
// Fonts are serialized to the form:
// "<family name>-<style>-<size>"
Font font = (Font) fontCache.get(fontString);
if (font != null) {
return font;
}
StringTokenizer tokenizer = new StringTokenizer(fontString, "-");
return new Font(tokenizer.nextToken(), Integer.parseInt(tokenizer
.nextToken()), Integer.parseInt(tokenizer.nextToken()));
}
private Icon lookupIcon(TopicIF type, TopicIF filenameTopic,
TopicIF iconTopic) {
String filename = getOccurrenceValue(type, filenameTopic);
if (filename == null)
return null;
ImageIcon icon = (ImageIcon) iconCache.get(filename);
if (icon == null) {
String base64 = getOccurrenceValue(type, iconTopic);
if (base64 == null)
return null;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
Base64Decoder.decode(base64, output);
} catch (IOException e) {
throw new OntopiaRuntimeException(e);
}
icon = new ImageIcon(output.toByteArray());
iconCache.put(filename, icon);
}
return icon;
}
public void setTypeIconFilename(TopicIF type, String string) {
if (string == null) {
removeOccurence(type, typeIconFilename);
removeOccurence(type, typeIcon);
} else
setIcon(type, string, typeIconFilename, typeIcon);
}
private void setIcon(TopicIF topictype, String string, TopicIF filenameTopic,
TopicIF iconTopic) {
setOccurenceValue(topictype, filenameTopic, string);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
FileInputStream file = new FileInputStream(string);
StreamUtils.transfer(file, output);
file.close();
byte[] bytes = output.toByteArray();
ImageIcon icon = new ImageIcon(bytes);
iconCache.put(string, icon);
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
output.reset();
Base64Encoder.encode(input, output);
} catch (IOException e) {
// should never occur
throw new OntopiaRuntimeException("INTERNAL ERROR", e);
}
try {
setOccurenceValue(topictype, iconTopic, output.toString("ISO-8859-1"));
} catch (UnsupportedEncodingException e1) {
throw new OntopiaRuntimeException(e1);
}
}
public boolean shouldDisplayRoleHoverHelp() {
return getOccurrenceValue(generalTopic, showRoleHoverHelp, true);
}
public boolean isMotionKillerEnabled() {
return getOccurrenceValue(generalTopic, enableMotionKiller, true);
}
public boolean shouldDisplayScopedAssociationNames() {
return getOccurrenceValue(generalTopic, displayScopedAssociationNames,
true);
}
public void shouldDisplayRoleHoverHelp(boolean value) {
setOccurenceValue(generalTopic, showRoleHoverHelp, value);
}
public void setMotionKillerEnabled(boolean value) {
setOccurenceValue(generalTopic, enableMotionKiller, value);
}
public void shouldDisplayScopedAssociationNames(boolean value) {
setOccurenceValue(generalTopic, displayScopedAssociationNames, value);
}
public void setPanelBackgroundColour(Color aColor) {
setColor(generalTopic, typeColor, aColor);
}
public Color getPanelBackgroundColour() {
Color colour = lookupColor(generalTopic, typeColor);
if (colour == null)
colour = DEFAULT_PANEL_BACKGROUND_COLOUR;
return colour;
}
public void setGeneralSingleClick(int anAction) {
setOccurrenceValue(generalTopic, singleMouseClick, anAction);
}
public void setGeneralLocalityAlgorithm(int anAction) {
setOccurrenceValue(generalTopic, localityAlgorithm, anAction);
}
public void setMotionKillerDelay(int seconds) {
setOccurrenceValue(generalTopic, motionKillerDelay, seconds);
}
public void setMaxTopicNameLength(int length) {
setOccurrenceValue(generalTopic, maxTopicNameLength, length);
}
public void setGeneralDoubleClick(int anAction) {
setOccurrenceValue(generalTopic, doubleMouseClick, anAction);
}
public int getGeneralDoubleClick() {
return getOccurrenceValue(generalTopic, doubleMouseClick,
DEFAULT_DOUBLE_CLICK);
}
public int getGeneralSingleClick() {
return getOccurrenceValue(generalTopic, singleMouseClick,
DEFAULT_SINGLE_CLICK);
}
public int getGeneralLocalityAlgorithm() {
return getOccurrenceValue(generalTopic, localityAlgorithm,
DEFAULT_LOCALITY_ALGORITHM);
}
public int getGeneralMotionKillerDelay() {
return getOccurrenceValue(generalTopic, motionKillerDelay,
DEFAULT_KILLER_DELAY);
}
public int getMaxTopicNameLength() {
return getOccurrenceValue(generalTopic, maxTopicNameLength,
DEFAULT_MAX_TOPIC_NAME_LENGTH);
}
public void setTypeIncluded(TopicIF type) {
setOccurenceValue(type, typeExcluded, false);
}
public void setTypeExcluded(TopicIF type) {
setOccurenceValue(type, typeExcluded, true);
}
public boolean isTypeExcluded(TopicIF aType) {
return getOccurrenceValue(aType, typeExcluded, false);
}
public void setScopingTopic(TopicIF scope) {
if (scope == null)
clearTopic(scopingTopic);
else {
setTopicReference(scopingTopic, scope, scope.getTopicMap().getStore()
.getBaseAddress().getAddress());
}
}
public void clearStartTopic() {
clearTopic(startTopic);
}
protected TopicIF getSourceLocator() {
return sourceLocator;
}
protected TopicIF getSubject() {
return subject;
}
protected TopicIF getSubjectIndicator() {
return subjectIndicator;
}
public void setInAssociationScopeFilter(TopicIF scope, boolean included) {
setOccurenceValue(scope, scopeFilter, included);
}
public boolean isInAssociationScopeFilter(TopicIF scope) {
return getOccurrenceValue(scope, scopeFilter, false);
}
public void setAssociationScopeFilterStrictness(int strictness) {
setOccurrenceValue(scopeFilter, filterStrictness, strictness);
}
public int getAssociationScopeFilterStrictness() {
int retVal = SHOW_ALL_ASSOCIATION_SCOPES;
String occurrenceValue = getOccurrenceValue(scopeFilter, filterStrictness);
try {
if (occurrenceValue != null)
retVal = Integer.parseInt(occurrenceValue);
} catch (NumberFormatException e) {
}
return retVal;
}
/**
* @return All topics that are used as scopes of associations and are used to
* filter associations in Vizigator.
*/
public Collection getAssociationScopeFilter() {
// Get all topics that have an occurrence of type scopeFilter of value true.
Collection retVal = new ArrayList();
// Note: making new ArrayList() to avoid ConcurrentModificationException.
Collection topics = new ArrayList(topicmap.getTopics());
for (Iterator topicsIt = topics.iterator(); topicsIt.hasNext();) {
TopicIF currentTopic = (TopicIF)topicsIt.next();
if (isInAssociationScopeFilter(currentTopic))
retVal.add(currentTopic);
}
return retVal;
}
}