/* 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_Resource.java
package gr.forth.ics.vrp.corevrp.model;

import java.net.*;
import java.util.*;
import gr.forth.ics.vrp.corevrp.*;
import gr.forth.ics.vrp.corevrp.vocabulary.*;

/** RDF_Resource.java - For Resources containing RDFS or RDF info.
  *
 * @author Karsten Tolle & Sofia Alexaki
 * @version 2.5  (30 Januar 2003)
  */
public class RDF_Resource extends Resource {

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

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

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

    /**
     * Cast a Resource to a RDF_Resource.
     */
    RDF_Resource(Resource res) {
	setID(res.getID());
    }

    // Variables
    /** List containing the comments of the Resource. */
    private ArrayList comment = null;
    /** List containing the comments of the Resource. */
    private ArrayList label = null;
    /** List containing the seeAlso statements of the Resource. */
    private ArrayList seeAlso = null;
    /** List containing the isDefinedBy statements of the Resource. */
    private ArrayList isDefinedBy = null;
    /** List containing the types of the Resource. */
    private ArrayList type = null;
    /** List containing the values of the Resource. */
    private ArrayList value = null;

    private RDF_Error e = new RDF_Error();


    // Getters and setters
    /**
     * Add a comment to the resource.
     */
    public void addcomment(Literal com) {
        if (comment == null) comment = new ArrayList(1);
        if (! comment.contains(com)) comment.add(com);
    }

    /**
     * Set the comments of the resource.
     */
    public void setcomment(ArrayList list) { comment = list; }

    /**
     * Get the comments of the resource.
     */
    public ArrayList getcomment() {
        if (comment == null) return new ArrayList(0);
        return comment;
    }


    /**
     * Add a label to the resource.
     */
    public void addlabel(Literal lab) {
        if (label == null) label = new ArrayList(1);
        if (! label.contains(lab)) label.add(lab);
    }


    /**
     * Set the labels of the resource.
     */
    public void setlabel(ArrayList list) { label = list; }

    /**
     * Get the labels of the resource.
     */
    public ArrayList getlabel() {
      if (label == null) return new ArrayList(0);
      return label;
    }


    /**
     * Add a seeAlso statement to the resource.
     */
    public void addseeAlso(int sA) {
      if (seeAlso == null) seeAlso = new ArrayList(1);
      Integer I = new Integer(sA);
      seeAlso.add(I);
    }

    /**
     * Set the seeAlso statements of the resource.
     */
    public void setseeAlso(ArrayList list) { seeAlso = list; }

    /**
     * Get the seeAlso statements of the resource.
     */
    public ArrayList getseeAlso() {
        if (seeAlso == null) return new ArrayList(0);
        return seeAlso;
    }


    /**
     * Add a isDefiniedBy statement to the resource.
     */
    public void addisDefinedBy(int iDB) {
      if (isDefinedBy == null) isDefinedBy = new ArrayList(1);
      Integer I = new Integer(iDB);
      isDefinedBy.add(I);
    }

    /**
     * Set the isDefinedBy statements of the resource.
     */
    public void setisDefinedBy(ArrayList list) { isDefinedBy = list; }

    /**
     * Get the isDefinedBy statements of the resource.
     */
    public ArrayList getisDefinedBy() {
      if (isDefinedBy == null) return new ArrayList(0);
      return isDefinedBy;
    }

    /**
     * Add a value statement to the resource.
     */
    public void addvalue(int val) {
      if (value == null) value = new ArrayList(1);
      Integer I = new Integer(val);
      value.add(I);
    }
    public void addvalue(Literal val) {
      if (value == null) value = new ArrayList(1);
      if (! value.contains(val)) value.add(val);
    }

    /**
     * Set the value statements of the resource.
     */
    public void setvalue(ArrayList list) { value = list; }

    /**
     * Get the value statements of the resource.
     */
    public ArrayList getvalue() {
        if (value == null) return new ArrayList(0);
        return value;
    }


    /**
     * Add a type to the resource. It is not allowed to mix the type: statement, class or property.
     */
    public void addtype(RDF_Class c, Existing ex) {
      if (type == null) {
        type = new ArrayList();
        type.add(c);
        return;
      }
      if (type.contains(c)) return;
      if (! (test_type(c, ex))) return;
      type.add(c);
    }

    private boolean test_type(RDF_Class c, Existing ex) {
	if (c.getID().startsWith(rdfschema.NS)) {
		if (c.getID().equals(rdfschema.Class)) {
			if (type.contains(ex.get(rdf.Property)) ||
			    type.contains(ex.get(rdf.Statement)) ||
			    type.contains(ex.get(rdf.Bag)) ||
			    type.contains(ex.get(rdf.Alt)) ||
			    type.contains(ex.get(rdfschema.Literal)) ||
			    type.contains(ex.get(rdf.Seq)) ) {
				e.emit_error(3, 24, "Class and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
		if (c.getID().equals(rdf.Property)) {
			if (type.contains(ex.get(rdfschema.Class)) ||
			    type.contains(ex.get(rdf.Statement)) ||
			    type.contains(ex.get(rdf.Bag)) ||
			    type.contains(ex.get(rdf.Alt)) ||
			    type.contains(ex.get(rdfschema.Literal)) ||
			    type.contains(ex.get(rdf.Seq)) ) {
				e.emit_error(3, 24, "Property and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
		if (c.getID().equals(rdfschema.Literal)) {
			if (type.contains(ex.get(rdfschema.Class)) ||
			    type.contains(ex.get(rdf.Property)) ||
			    type.contains(ex.get(rdf.Statement)) ||
			    type.contains(ex.get(rdf.Bag)) ||
			    type.contains(ex.get(rdf.Alt)) ||
			    type.contains(ex.get(rdf.Seq)) ) {
				e.emit_error(3, 24, "Literal and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
	}
	if (c.getID().startsWith(rdf.NS)) {
		if (c.getID().equals(rdf.Statement)) {
			if (type.contains(ex.get(rdfschema.Class)) ||
			    type.contains(ex.get(rdf.Property)) ||
			    type.contains(ex.get(rdf.Bag)) ||
			    type.contains(ex.get(rdf.Alt)) ||
			    type.contains(ex.get(rdfschema.Literal)) ||
			    type.contains(ex.get(rdf.Seq)) ) {
				e.emit_error(3, 24, "Statement and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
		if (c.getID().equals(rdf.Bag)) {
			if (type.contains(ex.get(rdfschema.Class)) ||
			    type.contains(ex.get(rdf.Property)) ||
			    type.contains(ex.get(rdf.Statement)) ||
			    type.contains(ex.get(rdf.Alt)) ||
			    type.contains(ex.get(rdfschema.Literal)) ||
			    type.contains(ex.get(rdf.Seq)) ) {
				e.emit_error(3, 24, "Bag and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
		if (c.getID().equals(rdf.Seq)) {
			if (type.contains(ex.get(rdfschema.Class)) ||
			    type.contains(ex.get(rdf.Property)) ||
			    type.contains(ex.get(rdf.Statement)) ||
			    type.contains(ex.get(rdf.Alt)) ||
			    type.contains(ex.get(rdfschema.Literal)) ||
			    type.contains(ex.get(rdf.Bag)) ) {
				e.emit_error(3, 24, "Sequence and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
		if (c.getID().equals(rdf.Alt)) {
			if (type.contains(ex.get(rdfschema.Class)) ||
			    type.contains(ex.get(rdf.Property)) ||
			    type.contains(ex.get(rdf.Statement)) ||
			    type.contains(ex.get(rdf.Bag)) ||
			    type.contains(ex.get(rdfschema.Literal)) ||
			    type.contains(ex.get(rdf.Seq)) ) {
				e.emit_error(3, 24, "Alternative and "+type+" for "+this.getID(), "RDF_Resource.addtype");
                                return false;
			}
		}
	}
        return true;
    }

    /**
     * Set the type of the resource. This method is used to
     * copy information to a new created class or property.
     * The type: class, property and statement will not be
     * mixed in the array list, so, we do not have to test this here.
     */
    public void settype(ArrayList list) {
	type = list;
    }

    /**
     * Get the type of the resource.
     */
    public ArrayList gettype() {
      if (type == null) return new ArrayList(1);
      return type;
    }

// what do we need this for? Database?
    /**
     * Returns 'true' if the type rdf:Property is specified for this resource.
     */
  //  public boolean isProperty() { return type.contains(rdf.Property); }

    /**
     * Returns 'true' if the type rdfs:Class is specified for this resource.
     */
  //  public boolean isClass() { return type.contains(rdfschema.Class); }

    /**
     * Returns 'true' if the type rdf:Statement is specified for this resource.
     */
   // public boolean isStatement() { return type.contains(rdf.Statement); }


    /**
    * 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) {
      ArrayList al = new ArrayList();
      if (this.seeAlso != null) {
        for (Iterator i = this.seeAlso.iterator(); i.hasNext();){
          Object o = i.next();
          if (o instanceof Integer) {
            Object obj = existing.get(((Integer)o).intValue());
            al.add(obj);
          } else al.add(o);
        }
        this.seeAlso = al;
        al = new ArrayList();
      }
      if (this.isDefinedBy != null) {
       for (Iterator i = this.isDefinedBy.iterator(); i.hasNext();){
          Object o = i.next();
          if (o instanceof Integer) {
            Object obj = existing.get(((Integer)o).intValue());
            al.add(obj);
          } else al.add(o);
        }
        this.isDefinedBy = al;
        al = new ArrayList();
      }
      if (this.value != null) {
        for (Iterator i = this.value.iterator(); i.hasNext();){
          Object o = i.next();
          if (o instanceof Integer) {
            Object obj = existing.get(((Integer)o).intValue());
            al.add(obj);
          } else al.add(o);
        }
        this.value = al;
        // need to uncomment the following line in case you want to add some more
        //al = new ArrayList();
      }
    } // end solve_links



    /**
     * For validation
     */
     public boolean has_type(RDF_Class type) {
      if (this.gettype().contains(type)) return true;
      // we might inherit the type
      for (int j=0; j<this.gettype().size(); ) {
        RDF_Class rdf_class = (RDF_Class)this.type.get(j++);
        if (rdf_class.inherit_sCO(type)) return true;
      }
      return false;
    }

}