All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.semanticweb.elk.reasoner.taxonomy.impl.AbstractUpdateableGenericTaxonomy Maven / Gradle / Ivy

/*
 * #%L
 * elk-reasoner
 * 
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2011 Oxford University Computing Laboratory
 * %%
 * 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.
 * #L%
 */
package org.semanticweb.elk.reasoner.taxonomy.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.semanticweb.elk.owl.interfaces.ElkEntity;
import org.semanticweb.elk.reasoner.taxonomy.model.ComparatorKeyProvider;
import org.semanticweb.elk.reasoner.taxonomy.model.GenericTaxonomyNode;
import org.semanticweb.elk.reasoner.taxonomy.model.Node;
import org.semanticweb.elk.reasoner.taxonomy.model.NodeFactory;
import org.semanticweb.elk.reasoner.taxonomy.model.NodeStore;
import org.semanticweb.elk.reasoner.taxonomy.model.NonBottomTaxonomyNode;
import org.semanticweb.elk.reasoner.taxonomy.model.Taxonomy;
import org.semanticweb.elk.reasoner.taxonomy.model.TaxonomyNode;
import org.semanticweb.elk.reasoner.taxonomy.model.TaxonomyNodeFactory;
import org.semanticweb.elk.util.collections.LazySetUnion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A generic implementation of class taxonomy.
 * 
 * @author Peter Skocovsky
 *
 * @param 
 *            The type of members of the nodes in this taxonomy.
 * @param 
 *            The immutable type of nodes in this taxonomy.
 * @param 
 *            The mutable type of nodes in this taxonomy.
 */
// @formatter:off
public abstract class AbstractUpdateableGenericTaxonomy<
				T extends ElkEntity,
				N extends GenericTaxonomyNode,
				UN extends UpdateableTaxonomyNode
		>
		extends AbstractDistinctBottomTaxonomy {
// @formatter:on

	private static final Logger LOGGER_ = LoggerFactory
			.getLogger(AbstractUpdateableGenericTaxonomy.class);

	/** The factory creating the nodes of this taxonomy. */
	private final NodeFactory nodeFactory_;

	/** The store containing non-bottom nodes in this taxonomy. */
	protected final UpdateableNodeStore nodeStore_;

	/** The canonical member of the top node. */
	protected final T topMember_;

	/** The listeners notified about the changes to node store. */
	protected final List> nodeStoreListeners_;

	/** The listeners notified about the changes to taxonomy. */
	protected final List> taxonomyListeners_;

	/**
	 * Constructor.
	 * 
	 * @param nodeStore
	 *            Node store for the nodes of this taxonomy.
	 * @param nodeFactory
	 *            Factory that creates nodes of this taxonomy.
	 * @param topMember
	 *            The canonical member of the top node.
	 */
	public AbstractUpdateableGenericTaxonomy(
			final UpdateableNodeStore nodeStore,
			final TaxonomyNodeFactory> nodeFactory,
			final T topMember) {
		super();
		this.nodeStore_ = nodeStore;
		this.nodeFactory_ = new NodeFactory() {
			@Override
			public UN createNode(final Iterable members,
					final int size) {
				return nodeFactory.createNode(members, size,
						AbstractUpdateableGenericTaxonomy.this);
			}
		};
		this.topMember_ = topMember;
		this.taxonomyListeners_ = new ArrayList>();
		this.nodeStoreListeners_ = new ArrayList>();
	}

	@Override
	public ComparatorKeyProvider getKeyProvider() {
		return nodeStore_.getKeyProvider();
	}

	@Override
	public TaxonomyNode getNode(final T elkClass) {
		TaxonomyNode result = nodeStore_.getNode(elkClass);
		if (result == null && getBottomNode().contains(elkClass)) {
			result = getBottomNode();
		}
		return result;
	}

	@Override
	public UN getNonBottomNode(final T elkEntity) {
		return nodeStore_.getNode(elkEntity);
	}

	@Override
	public Set> getNodes() {
		return new LazySetUnion>(nodeStore_.getNodes(),
				Collections.singleton(getBottomNode()));
	}

	@Override
	public Set getNonBottomNodes() {
		return nodeStore_.getNodes();
	}

	@Override
	public UN getTopNode() {
		return nodeStore_.getNode(topMember_);
	}

	@Override
	public abstract N getBottomNode();

	@Override
	public UN getCreateNode(final Collection members) {
		return nodeStore_.getCreateNode(members, members.size(), nodeFactory_);
	}

	@Override
	public boolean setCreateDirectSupernodes(
			final NonBottomTaxonomyNode subNode,
			final Iterable> superMemberSets) {

		final UN node = toInternalNode(subNode);

		// TODO: establish consistency by adding default parent to the nodes.

		boolean isSuperMemberSetsEmpty = true;

		for (final Collection superMembers : superMemberSets) {
			final UN superNode = getCreateNode(superMembers);
			isSuperMemberSetsEmpty = false;
			addDirectRelation(superNode, node);
		}

		if (node.trySetAllParentsAssigned(true)) {
			if (!isSuperMemberSetsEmpty) {
				fireDirectSupernodeAssignment(subNode,
						subNode.getDirectSuperNodes());
			}
			return true;
		}
		// else
		return false;
	}

	protected void addDirectRelation(final UN superNode, final UN subNode) {
		subNode.addDirectSuperNode(superNode);
		superNode.addDirectSubNode(subNode);
	}

	@Override
	public boolean removeDirectSupernodes(
			final NonBottomTaxonomyNode subNode) {

		final UN node = toInternalNode(subNode);

		if (!node.trySetAllParentsAssigned(false)) {
			return false;
		}

		final List superNodes = new ArrayList();

		// remove all super-class links
		synchronized (node) {
			superNodes.addAll(node.getDirectNonBottomSuperNodes());
			if (superNodes.isEmpty()) {
				return true;
			}
			for (final UN superNode : superNodes) {
				node.removeDirectSuperNode(superNode);
			}
		}

		for (final UN superNode : superNodes) {
			synchronized (superNode) {
				superNode.removeDirectSubNode(node);
			}
		}

		fireDirectSupernodeRemoval(subNode, superNodes);

		return true;
	}

	@Override
	public boolean removeNode(final T member) {
		if (nodeStore_.removeNode(member)) {
			LOGGER_.trace("removed node with member: {}", member);
			return true;
		}
		// else
		return false;
	}

	@Override
	public boolean addToBottomNode(final T member) {
		if (unsatisfiableClasses_.put(getKeyProvider().getKey(member),
				member) == null) {
			fireMemberForNodeAppeared(member, getBottomNode());
			return true;
		}
		// else
		return false;
	}

	@Override
	public boolean removeFromBottomNode(final T member) {
		if (unsatisfiableClasses_
				.remove(getKeyProvider().getKey(member)) != null) {
			fireMemberForNodeDisappeared(member, getBottomNode());
			return true;
		}
		// else
		return false;
	}

	@SuppressWarnings("unchecked")
	protected UN toInternalNode(final NonBottomTaxonomyNode node) {
		if (node.getTaxonomy() != this) {
			throw new IllegalArgumentException(
					"The sub-node must belong to this taxonomy: " + node);
		}
		// By construction, if the node is in this taxonomy, it is of type N.
		try {
			return (UN) node;
		} catch (final ClassCastException e) {
			throw new IllegalArgumentException(
					"The sub-node must belong to this taxonomy: " + node);
		}
	}

	@Override
	public boolean addListener(final NodeStore.Listener listener) {
		return nodeStore_.addListener(listener)
				&& nodeStoreListeners_.add(listener);
	}

	@Override
	public boolean removeListener(final NodeStore.Listener listener) {
		return nodeStore_.removeListener(listener)
				&& nodeStoreListeners_.remove(listener);
	}

	@Override
	public boolean addListener(final Taxonomy.Listener listener) {
		return taxonomyListeners_.add(listener);
	}

	@Override
	public boolean removeListener(final Taxonomy.Listener listener) {
		return taxonomyListeners_.remove(listener);
	}

	protected void fireMemberForNodeAppeared(final T member,
			final Node node) {
		for (final NodeStore.Listener listener : nodeStoreListeners_) {
			listener.memberForNodeAppeared(member, node);
		}
	}

	protected void fireMemberForNodeDisappeared(final T member,
			final Node node) {
		for (final NodeStore.Listener listener : nodeStoreListeners_) {
			listener.memberForNodeDisappeared(member, node);
		}
	}

	protected void fireDirectSupernodeAssignment(final TaxonomyNode subNode,
			final Collection> superNodes) {
		for (final Taxonomy.Listener listener : taxonomyListeners_) {
			listener.directSuperNodesAppeared(subNode);
			for (final TaxonomyNode superNode : superNodes) {
				listener.directSubNodesAppeared(superNode);
			}
		}
	}

	protected void fireDirectSupernodeRemoval(final TaxonomyNode subNode,
			final Collection> superNodes) {
		for (final Taxonomy.Listener listener : taxonomyListeners_) {
			listener.directSuperNodesDisappeared(subNode);
			for (final TaxonomyNode superNode : superNodes) {
				listener.directSubNodesDisappeared(superNode);
			}
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy