/* This software was developed within the context of the project Metaphor for Science
   Museums (Mesmuses) in the framework of the Information Society Technology
   Programme, part of the Fifth Research And Technological Development
   Framework Programme of the European Community, under the Consortium
   Agreement dated <June 30, 2001>, between INRIA, Finsiel Spa, IMSS,
   Valoris , CSI, ICS-FORTH, ENSTB, EDW International.
*/
// RDF_Property.java
package gr.forth.ics.vrp.corevrp.model;

import java.net.*;
import java.util.*;
import java.lang.Exception;


/** RDF_Property.java - The class for the Properties.
  *
 * @author Karsten Tolle & Sofia Alexaki
 * @version 2.5  (30 Januar 2003)
  */
public class RDF_Property extends RDF_Resource  {

    /**
     * Create a new RDF_Property.
     */
    RDF_Property() { };

    /**
     * Create a new RDF_Property and set the URI.
     */
    RDF_Property(URL theURI) {
	setID(theURI.toString());
    };

    /**
     * Create a new RDF_Property and set the URI.
     */
    RDF_Property(String theURI) {
	setID(theURI);
    };

    /**
     * Casting a Resource to a new RDF_Property.
     */
    public RDF_Property(Resource res) {
	setID(res.getID());
    }

    /**
     * Casting a RDF_Resource to a new RDF_Property.
     */
    public RDF_Property(RDF_Resource res) {
	setID(res.getID());
  	setcomment(res.getcomment());
	setlabel(res.getlabel());
	setseeAlso(res.getseeAlso());
	setisDefinedBy(res.getisDefinedBy());
	setvalue(res.getvalue());
	settype(res.gettype());
    }

    // Variables
    /** Containing all direct superproperties of this property.*/
    private ArrayList subPropertyOf = new ArrayList(2);
    /** The range of the property.*/
    private ArrayList range = new ArrayList(1);
    /** The domains of the property.*/
    private ArrayList domain = new ArrayList(1);
    /** A list of subjects and objects the property connects.*/
    private ArrayList link_list = new ArrayList();

    // Getters and setters
    /**
     * Entering a subPropertyOf statement to the property.
     */
    public void addsubPropertyOf(RDF_Property subPO) { if (! (subPropertyOf.contains(subPO))) subPropertyOf.add(subPO); }

    /**
     * Getting all subPropertyOf statements of the property.
     */
    public ArrayList getsubPropertyOf() { return subPropertyOf; }

    /**
     * Set the range(s) of the property
     */
    //Changed 10 August 2001 by Sofia Alexaki
    // Now, the RDF Properties can have multiple ranges.
    public void addrange(RDF_Class r) {
      if (! (range.contains(r))) {
		   range.add(r);
		// System.out.println("entered "+d+" to domain of "+this.getID());
	   }
    }

    /**
     * Get the range of the property.
     */
    public  ArrayList getrange() {
	   return range;
    }

    /**
     * Set the domain(s) of the property.
     */
public void adddomain(RDF_Class d) {
	if (! (domain.contains(d))) {
		domain.add(d);
		// System.out.println("entered "+d+" to domain of "+this.getID());
	}
    }

   /**
    * Sets the  range(s) of the property.
    */
     public void setrange(ArrayList range) {
        this.range = range;
	  }

	/**
	 * Sets the subProperties of the property.
	 */
	 public void setsubPropertyOf(ArrayList subPropertyOf) {
	 	this.subPropertyOf = subPropertyOf;
	 }

    /**
     * Getting the domain(s) of the property.
     */
    public ArrayList getdomain() { return domain; }


    /**
     * Setting the domain(s) of the property.
     */
    public void setdomain(ArrayList dom) { this.domain = dom; }


    /**
     * Add a link(subject, object) to the property.
     */
    public void addlink(int subj, int obj) {
		 if (! link_contains(subj, obj)) {
		   Link link = new Link(subj, obj);
      	link_list.add(link);
	    }
    }

    /**
     * Add a link(subject, object) to the property with object being a Literal.
     */
    void addlink(int subj, Literal obj) {
		 if (! link_contains(subj, obj)) {
		   Link link = new Link(subj, obj);
      	link_list.add(link);
	    }
    }


    /**
     * Tests if the list of links already contains the link(subject, object).
     */
    boolean link_contains(int subj, int obj) {
	Link link;
	int subject;
        Object object;
	for (int i=0; i<link_list.size(); ) {
		link = (Link)link_list.get(i++);
                object = link.getobject();
                if (object instanceof Literal) return false;
		subject = link.getsubject_int();
		if (subject == subj) {
                  Integer INT = (Integer)object;
                  if (INT.intValue() == obj) return true;
		}
	}
	return false;
    }


   /**
     * Tests if the list of links already contains the link(subject, object).
     */
    boolean link_contains(int subj, Literal obj) {
	Link link;
	int subject;
        Object object;
	for (int i=0; i<link_list.size(); ) {
		link = (Link)link_list.get(i++);
                object = link.getobject();
                if (! (object instanceof Literal)) return false;
                Literal l = (Literal)object;
		subject = link.getsubject_int();
		if (subject == subj) {
			if (l.equals(obj)) return true;
		}
	}
	return false;
    }



    /**
     * Getting all links of the property.
     */
    public ArrayList getlink() { return link_list; }


    /**
    * This method is for changing the Integer to links to the real java objects
    * so, we do not need the HashTables any more.
    */
    public void solve_links(Existing existing) {
      // the links need to be solved
      ArrayList al = new ArrayList();
      for (Iterator i = link_list.iterator(); i.hasNext();) {
        Link l = (Link)i.next();
        l.solve_links(existing);
        al.add(l);
      }
      this.link_list = al;
      super.solve_links(existing);
    }


    public boolean range_domain_check() throws Exception {
        for (Iterator i = this.link_list.iterator();i.hasNext();) {
            Link l = (Link)i.next();
            try {
                l.domain_range_check(this.getdomain(),this.getrange());
            } catch(Exception e) {
                throw new Exception(e.getMessage()+" used with "+this.getID());
            }
        }
        return true;
        /*
        ArrayList range_list = rdf_property.getrange();
    if ( isRangeMultiDefined(rdf_property) )
      ;
    else if ( isRangeUnique(rdf_property) ) {
  	  r = true;
  	}
		ArrayList domain_list = rdf_property.getdomain();
		if (domain_list.size() > 0) { // we have a domain set for range
			// System.out.println(domain_list);
			d = true;
		}
		// System.out.println("r and d set");
		if (r || d) {
 		  // we have a range and/or domain set for this property
		  // and now need to check each link for the given domain and/or range
		  ArrayList links = rdf_property.getlink();
		  for (int i=0; i<links.size(); ) {
			Link link = (Link)links.get(i++);
			if (r) { // if range is given
				Object obj = link.getobject();
				range_check(Property_ID, obj, range_list);
			} // end if (r)
			if (d) { // if domain is given
				int subj_int = link.getsubject_int();
                                Resource subj_res = basis_model.getResource(subj_int);
                                String subj = subj_res.getID();
				domain_check(Property_ID, subj, domain_list);
			} //end if (d)
		  } //end links
		} // end if (r||d)
	   } // end if property
	 } // end for loop
	  // System.out.println("out domain_range_check");
          */
    }

}

