/* $Id: RWRepository.java 454 2011-10-26 14:22:00Z minao $ */
/*
 * 作成日: 2006/06/02
 *
 */
package reasoning_web.logical;

import java.util.ArrayList;
import java.util.List;

import reasoning_web.logical.inter_face.RWElement;
import smart_gs.image_search.normal.swingui.Observer;
import smart_gs.logical.GSResource;


/**
 * @author kazuaki kobayashi
 * 
*/
public class RWRepository {
	
	protected List<GSResource> resourceBaskets;
	protected List<Connection> connections;
	protected List<ResourcePointer> pointers;
	private Factory factory;
	private List<Observer> observers;
	
	protected RWRepository(){
		this.factory = this.getFactory();
		this.connections = new ArrayList<Connection>();
		this.pointers = new ArrayList<ResourcePointer>();
		this.observers = new ArrayList<Observer>();
		this.resourceBaskets = new ArrayList<GSResource>();
	}
	public void initialize(){
		this.connections.clear();
		this.pointers.clear();
	}
	protected Factory getFactory() {
		return new DefaultFactory();
	}
	/**
	 * ResourcePointer of an element of RWElement is returned
	 * @param element
	 * @return
	 */
	public ResourcePointer getResourcePointer(RWElement element){
		for(int i=0;i<this.pointers.size();i++){
			if(this.pointers.get(i).getRwElement().equals(element)){
				return this.pointers.get(i);
			}
		}
		return null;
	}
	
	public boolean isRegistered(RWElement element){
		for(int i=0;i<this.pointers.size();i++){
			if(this.pointers.get(i).getRwElement().equals(element)){
				return true;
			}
		}
		return false;
	}
	/**
	 * sourceとtarget間にconnectionを作成する。
	 * noteはそのconnecitonに付随する
	 * 
	 * @param source
	 * @param target
	 * @param note
	 */
	public void createConnection(RWElement source,RWElement target,
			ExplanatoryNote note){
		ResourcePointer sourcePointer;
//		This makes a pointer unique to each element
		if(!this.isRegistered(source)){
			sourcePointer = factory.createResourcePointer(source);
			this.register(sourcePointer);
		}else{
			sourcePointer = this.getResourcePointer(source);
		}
		
		ResourcePointer targetPointer;
		if(!this.isRegistered(target)){
			targetPointer = this.factory.createResourcePointer(target);
			this.register(targetPointer);
		}else{
			targetPointer = this.getResourcePointer(target);
		}
		this.addConnection(sourcePointer, targetPointer, note);
	}

	public Connection getNewestConnection() {
		return connections.get(connections.size()-1);
	}
	protected void register(ResourcePointer pointer){
		if(!this.pointers.contains(pointer)){
			this.pointers.add(pointer);
		}
		this.notifyChange();
	}
	/**
	 * sourceとtarget間にconnectionを作成する。
	 * noteはそのconnecitonに付随する
	 * 
	 * @param source
	 * @param target
	 * @param note
	 */
	private void addConnection(ResourcePointer source,ResourcePointer target,
			ExplanatoryNote note){
		this.connections.add(this.factory.createConnection(source, target, note));
	}

	protected void addConnection(Connection connection){
		this.connections.add(connection);
	}
	/**
	 * elementで指定されたResourceをReasoning Webに登録する
	 * @param element
	 */
	public void register(RWElement element){
		ResourcePointer pointer = this.factory.createResourcePointer(element);
		this.pointers.add(pointer);
		this.notifyChange();
	}
	/**
	 * elementで指定されたresourceがリンクを持つか調べる
	 * @param element
	 * @return 
	 */

	public boolean hasLink(RWElement element){
		ResourcePointer pointer = this.getResourcePointer(element);
		if(pointer == null){
			return false;
		}
		return pointer.hasLink();
	}

	public boolean hasLinkTarget(RWElement element){
		ResourcePointer pointer = this.getResourcePointer(element);
		if(pointer == null){
			return false;
		}
		return pointer.hasTarget();
	}

	public boolean hasLinkSource(RWElement element){
		ResourcePointer pointer = this.getResourcePointer(element);
		if(pointer == null){
			return false;
		}
		return pointer.hasSource();
	}
	
	public int getLinkType(RWElement element) {
		if (this.hasLinkTarget(element) && this.hasLinkSource(element)) {
			return ResourcePointer.BOTH;
		} else if (this.hasLinkSource(element)) {
			return ResourcePointer.IN;
		} else if (this.hasLinkTarget(element)) {
			return ResourcePointer.OUT;
		} else {
			return -1;
		}
	}

	
	
	/**
	 * すべてのconnectionを返す
	 * @return
	 */
	public List<Connection> getConnections(){
		return this.connections;
	}
	/**
	 * 現在登録されているすべてのResourcePointerを返す
	 * @return
	 */
	public List<ResourcePointer> getResourcePointers(){
		return this.pointers;
	}
	
	public List<RWElement> getDirectElements(ResourcePointer pointer){
		if(pointer == null){
			return null;
		}
		return pointer.getDirectLinkElements();
	}
	public void addObserver(Observer observer){
		this.observers.add(observer);
	}
	public void notifyChange(){
		for(int i=0;i<this.observers.size();i++){
			this.observers.get(i).update();
		}
	}
}
