/* * #! * 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.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.util.Iterator; import net.ontopia.infoset.core.LocatorIF; import net.ontopia.infoset.impl.basic.URILocator; import net.ontopia.topicmaps.core.OccurrenceIF; import net.ontopia.topicmaps.core.TMObjectIF; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapBuilderIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.topicmaps.impl.basic.InMemoryTopicMapStore; import net.ontopia.topicmaps.utils.CharacteristicUtils; import net.ontopia.topicmaps.utils.NullResolvingExternalReferenceHandler; import net.ontopia.topicmaps.xml.XTMTopicMapReader; import net.ontopia.topicmaps.xml.XTMTopicMapWriter; import net.ontopia.utils.OntopiaRuntimeException; import net.ontopia.utils.URIUtils; /** * INTERNAL: Abstract configuration manager class. */ public abstract class VizConfigurationManager { protected TopicMapBuilderIF builder; protected TopicMapIF topicmap; protected static final String BASE = "http://psi.ontopia.net/viz/"; //Stores general configuration for the Vizigator. protected TopicIF generalTopic; // Stores configuration information for untyped topics. protected TopicIF untypedTopic; // Configures all topic types that have no explicit configuration. protected TopicIF defaultType; // Configures all association types that have no explicit configuration. protected TopicIF defaultAssociationType; protected static final String GENERAL_TOPIC = BASE + "vizigator-general"; protected static final String DEFAULT_TYPE = BASE + "default-type"; protected static final String UNTYPED = BASE + "untyped"; protected static final String DEFAULT_ASSOCIATION_TYPE = BASE + "default-association-type"; /** * Creates an empty configuration manager where everything is set to default. */ public VizConfigurationManager() { init(); } /** * Constructor initializes the configuration by loading a topic map from the * URL given in the parameter. */ public VizConfigurationManager(File tmfile) throws IOException { this(URIUtils.toURL(tmfile).toExternalForm()); } /** * Constructor initializes the configuration by loading a topic map from the * URL given in the parameter. */ public VizConfigurationManager(String tmurl) throws IOException { if (tmurl != null) { XTMTopicMapReader reader = new XTMTopicMapReader(tmurl); reader.setExternalReferenceHandler(new NullResolvingExternalReferenceHandler()); reader.setValidation(false); // means we don't need Jing try { topicmap = reader.read(); } catch (OntopiaRuntimeException e) { // if we can't read the configuration, carry on anyway // init() will make a blank TM for us } } if (topicmap == null) topicmap = new InMemoryTopicMapStore().getTopicMap(); init(); } /** * Returns the occurrence of the given type, if there is one. */ protected OccurrenceIF getOccurrence(TopicIF topic, TopicIF type) { return CharacteristicUtils.getByType(topic.getOccurrences(), type); } /** * Removes the occurrence of a given type from a given configuration topic. * Returns true iff the occurrence was found and removed. */ protected boolean removeOccurrence(TopicIF topic, TopicIF type) { if (topic == null) return false; OccurrenceIF occurrence = CharacteristicUtils .getByType(topic.getOccurrences(), type); if (occurrence == null) return false; occurrence.remove(); return true; } /** * Looks up a topic by subject indicator, creating it if it can't be found. If * a new topic is created, assign "basename" as a basename. */ protected TopicIF getTopic(String indicator, String basename) { try { LocatorIF loc = new URILocator(indicator); TopicIF t = topicmap.getTopicBySubjectIdentifier(loc); if (t == null) { t = builder.makeTopic(); if (basename != null) { builder.makeTopicName(t, basename); } t.addSubjectIdentifier(loc); } return t; } catch (MalformedURLException mue) { throw new OntopiaRuntimeException(Messages .getString("Viz.MalformedURLForTopicSubjectIndicator"), mue); } } /** * Looks up a topic by subject indicator, creating it if it can't be found. */ protected TopicIF getTopic(String indicator) { return getTopic(indicator, null); } public TopicMapIF getTopicMap() { return topicmap; } protected void removeOccurence(TopicIF type, TopicIF occtype) { TopicIF target = getConfigTopic(type); OccurrenceIF occ = getOccurrence(target, occtype); if (occ != null) getOccurrence(target, occtype).remove(); } protected void setOccurenceValue(TopicIF type, TopicIF occtype, String value) { TopicIF cfgtopic = getConfigTopic(type); OccurrenceIF occ = getOccurrence(cfgtopic, occtype); if (value == null) return; // don't make the occ if there is no value to give it if (occ == null) occ = builder.makeOccurrence(cfgtopic, occtype, value); else occ.setValue(value); } /** * Sets the Shape setting for this association or topic type in the topic map. */ protected void setOccurrenceValue(TopicIF type, TopicIF occtype, int integer) { setOccurenceValue(type, occtype, (new Integer(integer)).toString()); } /** * Sets the visibility setting for this association or topic type in the topic * map. */ protected void setOccurenceValue(TopicIF type, TopicIF occtype, boolean value) { setOccurenceValue(type, occtype, (new Boolean(value)).toString()); } public String getOccurrenceValue(TopicIF type, TopicIF occtype) { TopicIF cfgtopic = getConfigTopic(type); if (cfgtopic == null) return null; OccurrenceIF occ = getOccurrence(cfgtopic, occtype); if (occ == null) return null; return occ.getValue(); } protected boolean getOccurrenceValue(TopicIF type, TopicIF occtype, boolean defaultBoolean) { String value = getOccurrenceValue(type, occtype); if (value == null) return defaultBoolean; return "true".equalsIgnoreCase(value); } protected int getOccurrenceValue(TopicIF type, TopicIF occtype, int defaultInt) { String value = getOccurrenceValue(type, occtype); if (value == null) return defaultInt; return Integer.parseInt(value); } public void save(File f) throws IOException { XTMTopicMapWriter writer = new XTMTopicMapWriter(f); writer.write(topicmap); } protected void init() { if (topicmap == null) { InMemoryTopicMapStore store = new InMemoryTopicMapStore(); topicmap = store.getTopicMap(); // we set a base address for the topic map so that we can have // <base>#<id> URIs inside the topic map. this is used to avoid // portability problems with local ids in visualized topic maps try { store.setBaseAddress(new URILocator("x-ontopia:this:is:a:fake:url")); } catch (MalformedURLException e) { throw new OntopiaRuntimeException("IMPOSSIBLE ERROR", e); } } builder = topicmap.getBuilder(); generalTopic = getTopic(GENERAL_TOPIC); untypedTopic = getTopic(UNTYPED); defaultType = getTopic(DEFAULT_TYPE); defaultAssociationType = getTopic(DEFAULT_ASSOCIATION_TYPE); } /** * If the locator is of the form <base># <id>the <id>part is returned, * otherwise we return null. (Note that base will already contain the '#' at * the end.) */ private String relativize(String base, LocatorIF locator) { if (base == null) return null; String uri = locator.getAddress(); if (uri.startsWith(base)) return uri.substring(base.length()); return null; } /** * Looks up the corresponding topic (from the visualized topic map) in the * configuration topic map, creating one if it doesn't exist. */ protected TopicIF getConfigTopic(TopicIF real) { if (real == null) return untypedTopic; // setting up some variables for use later LocatorIF cfgloc = topicmap.getStore().getBaseAddress(); LocatorIF _baseAddress = real.getTopicMap().getStore().getBaseAddress(); String realbase = (_baseAddress == null ? null : _baseAddress.getAddress() + '#'); // try to look topic up TopicIF cfg = null; Iterator<LocatorIF> it = real.getSubjectLocators().iterator(); while (cfg == null && it.hasNext()) { LocatorIF loc = it.next(); cfg = topicmap.getTopicBySubjectLocator(loc); if (cfg == null) { // is this branch ever used? TMObjectIF obj = topicmap.getObjectByItemIdentifier(loc); if (obj instanceof TopicIF) cfg = (TopicIF) obj; } String id = relativize(realbase, loc); if (cfg == null && id != null) cfg = topicmap.getTopicBySubjectIdentifier(cfgloc.resolveAbsolute('#' + id)); } it = real.getSubjectIdentifiers().iterator(); while (cfg == null && it.hasNext()) { LocatorIF loc = it.next(); cfg = topicmap.getTopicBySubjectIdentifier(loc); if (cfg == null) { // is this branch ever used? TMObjectIF obj = topicmap.getObjectByItemIdentifier(loc); if (obj instanceof TopicIF) cfg = (TopicIF) obj; } String id = relativize(realbase, loc); if (cfg == null && id != null) cfg = topicmap.getTopicBySubjectIdentifier(cfgloc.resolveAbsolute('#' + id)); } it = real.getItemIdentifiers().iterator(); while (cfg == null && it.hasNext()) { LocatorIF loc = it.next(); cfg = (TopicIF) topicmap.getObjectByItemIdentifier(loc); if (cfg == null) cfg = topicmap.getTopicBySubjectIdentifier(loc); String id = relativize(realbase, loc); if (cfg == null && id != null) cfg = (TopicIF) topicmap.getObjectByItemIdentifier(cfgloc .resolveAbsolute('#' + id)); } // if topic doesn't exist, create it if (cfg == null) { cfg = builder.makeTopic(); it = real.getSubjectLocators().iterator(); while (it.hasNext()) { LocatorIF loc = it.next(); String id = relativize(realbase, loc); if (id != null) loc = cfgloc.resolveAbsolute('#' + id); cfg.addSubjectLocator(loc); } it = real.getSubjectIdentifiers().iterator(); while (it.hasNext()) { LocatorIF loc = it.next(); String id = relativize(realbase, loc); if (id != null) loc = cfgloc.resolveAbsolute('#' + id); cfg.addSubjectIdentifier(loc); } it = real.getItemIdentifiers().iterator(); while (it.hasNext()) { LocatorIF loc = it.next(); String id = relativize(realbase, loc); if (id != null) loc = cfgloc.resolveAbsolute('#' + id); cfg.addItemIdentifier(loc); } } // finally done return cfg; } }