/*
* #!
* Ontopia Engine
* #-
* 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.entry;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import net.ontopia.topicmaps.core.StoreDeletedException;
import net.ontopia.topicmaps.core.TopicMapStoreIF;
import net.ontopia.topicmaps.core.events.AbstractTopicMapListener;
import net.ontopia.topicmaps.core.events.TopicMapListenerIF;
import net.ontopia.utils.ObjectUtils;
import net.ontopia.utils.OntopiaRuntimeException;
/**
* INTERNAL: An abstract topic map reference class that contains
* methods that handles the id and title properties. Subclasses should
* implement the createStore method.<p>
*/
public abstract class AbstractTopicMapReference
implements TopicMapReferenceIF {
protected String id;
protected String title;
protected boolean isopen;
protected boolean deleted;
protected TopicMapSourceIF source;
public AbstractTopicMapReference(String id, String title) {
this.id = id;
this.title = title;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public TopicMapSourceIF getSource() {
return source;
}
public void setSource(TopicMapSourceIF source) {
this.source = source;
}
public boolean isOpen() {
return isopen;
}
public synchronized void open() {
if (isDeleted())
throw new StoreDeletedException("Topic map has been deleted through this reference.");
this.isopen = true;
}
public synchronized void close() {
this.isopen = false;
}
public boolean isDeleted() {
return deleted;
}
public synchronized void delete() {
if (source == null)
throw new UnsupportedOperationException("This reference cannot be deleted as it does not belong to a source.");
if (!source.supportsDelete())
throw new UnsupportedOperationException("This reference cannot be deleted as the source does not allow deleting.");
// ignore if store already deleted
if (isDeleted()) return;
// close the reference
close();
this.deleted = true;
}
public synchronized void clear() throws IOException {
// naive implementation that gets a store and clears it
TopicMapStoreIF store = null;
try {
store = createStore(false);
store.getTopicMap().clear();
} finally {
if (store != null && store.isOpen()) store.close();
}
}
public abstract TopicMapStoreIF createStore(boolean readonly)
throws IOException;
// -- store pooling
public void storeClosed(TopicMapStoreIF store) {
}
// ---------------------------------------------------------------------------
// TopicMapListenerIF implementation
// ---------------------------------------------------------------------------
protected List<TopicMapListenerIF> listeners;
protected TopicMapListenerIF[] topic_listeners;
protected TopicMapListenerIF[] getTopicListeners() {
return topic_listeners;
}
// NOTE: called every time listener changes
protected void setTopicListeners(TopicMapListenerIF[] topic_listeners) {
this.topic_listeners = topic_listeners;
}
/**
* INTERNAL: Add topic listener to reference.
*/
public synchronized void addTopicListener(TopicMapListenerIF listener) {
if (topic_listeners == null)
listeners = new ArrayList<TopicMapListenerIF>(3);
listeners.add(listener);
makeListenerArray();
// register self with listener
if (listener instanceof AbstractTopicMapListener)
((AbstractTopicMapListener)listener).setReference(this);
}
/**
* INTERNAL: Remove topic listener from reference.
*/
public synchronized void removeTopicListener(TopicMapListenerIF listener) {
if (topic_listeners == null) return;
listeners.remove(listener);
makeListenerArray();
// unregister self with listener
if (listener instanceof AbstractTopicMapListener)
((AbstractTopicMapListener)listener).setReference(null);
}
/**
* INTERNAL: Register topic listener from list of listener implementations.
*/
public synchronized void registerTopicListeners(String listenerList) {
StringTokenizer st = new StringTokenizer(listenerList, ", ");
while (st.hasMoreTokens()) {
Object object = ObjectUtils.newInstance(st.nextToken());
if (object instanceof TopicMapListenerIF)
addTopicListener((TopicMapListenerIF)object);
else
throw new OntopiaRuntimeException("Listener " + object + " is not a TopicMapListenerIF and cannot be added to reference with id " + getId());
}
}
protected void makeListenerArray() {
if (listeners == null || listeners.isEmpty()) {
this.listeners = null;
setTopicListeners(null);
} else {
TopicMapListenerIF[] tls = new TopicMapListenerIF[listeners.size()];
listeners.toArray(tls);
setTopicListeners(tls);
}
}
}