/* 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.
*/

/*
 *  CHANGE LOG:
 *  Each entry starts with a date, who did the changed and what has been done.
 *  Separated by ':'.
 *
 *  28.02.2002 : Karsten Tolle : Inference of types for subclasses as an optional feature.
 *  01.03.2002 : Karsten Tolle : Bug fix: Generate a Container when add tpye rdfs:Container.
 *  30.04.2002 : Karsten Tolle : All rdf and rdfs triples will be entered to the model.
 *  24.05.2002 : Karsten Tolle : Changed genSysID() to take xml:base into account.
 *  13.06.2002 : Karsten Tolle : Added rdfs:subPropertyOf for all rdf:_nn to rdfs:member.
 *  05.09.2002 : Karsten Tolle : Change of the used underlying datastructure by introducint the
 *                               the new class Existing.
 *
 *  14.11.2002 : Karsten Tolle : Fixed bug in the dump method.
 *  14.11.2002 : Karsten Tolle : Enabled to use string version of rdf & rdfschema
 *                               as specified in the corresponding vocabularies.
 *  26.12.2002 : Karsten Tolle : Changed the Literals (included language and datatype).
 *                               Therefore also change the addStatement methode and
 *                               some minor things.
 *
 *  15.01.2003 : Sofia Alexaki : The method getModelPart is added.
 *
 *  20.01.2003 : Sofia Alexaki : The methods getMetaClasses, getMetaProperties
 *                                and getAllMetaClasses
 *  30.01.2003 : Karsten Tolle : Added test_msp method for testing rdf:_nn where
 *                               nn needs to be an integer greater zero with no leading zeros.
 *
 */

// Model.java

package gr.forth.ics.vrp.corevrp.model;

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


/**
  * Model.java - All we can do to a model.
  *
  * @author Karsten Tolle & Sofia Alexaki
  * @version 2.5  (30 Januar 2003)
  */
public class Model extends Resource implements IModel{

	 // Variables
	 public Existing existing = null;


	 /** Counter for the creation of the generic generated IDs.*/
	 private int anonymos = 1; // used for generic ID production
	 /** Containing the pathname of the corresponding file.*/
	 private String BaseURI = "";
	 /** For reporting errors.*/
	 private RDF_Error e = new RDF_Error();
	 /** Hash map containing models of namespaces.*/
	 private HashMap model_list = new HashMap();
	 /** Containing URIs for elements we entered the information from the namespace.*/
	 private ArrayList done_list = new ArrayList();

	 /** Containing the URI and the object reference of all external namespaces
	  * that have been parsed
	  */
	 private HashMap namespaces = new HashMap();

	 private boolean verbose = false;
  /**
	* Sets whether messages about the actions performed by the VRP will be reported.
	*/
	 public void setverbose(boolean b) { this.verbose = b; }
  /**
	*  Indicates whether messages about the actions performed by the VRP will be reported.
	*/
	 public boolean getverbose() { return verbose; }
	 private boolean getandadd = false;
	 // the following namespaces will be used to enter the rdf and rdfs information to the model
/*    private String myrdfschemans = "http://www.dbis.informatik.uni-frankfurt.de/~tolle/RDF/Namespaces/rdf-schema.xml";
	 private String myrdfns = "http://www.dbis.informatik.uni-frankfurt.de/~tolle/RDF/Namespaces/22-rdf-syntax-ns.xml";*/
	 private String myrdfschemans = "http://139.91.183.30:9090/RDF/VRP/Examples/22-rdf-syntax-ns.rdf";
	 private String myrdfschemaXML = rdfschema.XMLRep;
	 private String myrdfns = "http://139.91.183.30:9090/RDF/VRP/Examples/rdf-schema.rdf";
	 private String myrdfXML = rdf.XMLRep;

	 /** Create a new model.
	 */
	 public Model(boolean init) {
		existing = new Existing(init);
	 };

	 public void setNamespaces(HashMap ns) { this.namespaces = ns; }

	/**
	 * Returns a HashMap. The key of hashmap is the URIs of the resource.
	 * The value is the respective VRP object (RDF_Class, RDF_Property,
	 * RDF_Container, RDF_Statement, RDF_Resource and Resource) created for the resource
	 */
	/* public HashMap getexisting() {
		 return existing;
	 }*/

	 /**
	  * Entering a statement to the model.
	  */
	 public void addStatement(String pred, String subj, Object o) {
	 String obj;
			Literal obj_lit = null;
			boolean res = true;
			if (o instanceof Literal) {
				res = false;
				obj_lit = (Literal)o;
				obj = obj_lit.toString();
		  } else {
				obj = o.toString();
		  }

	Object predicate, subject, object;
		  int subj_int, pred_int, obj_int = 0;

	// final strings for error messages
	final String statement = "Tripel: "+pred+", "+subj+", "+obj;

	RDF_Class rdf_class;
	RDF_Property rdf_property;
	RDF_Resource rdf_resource;
	Link link;


	// Testing in the case that subj or obj starts with RDF or RDF-Schema namespace
	// if they belong to the namespace.
	RDF_test(subj);
	if (res) RDF_test(obj);

	// the predicate
		  pred_int = enter_Property(pred);
	if (((pred.startsWith(rdfschema.NS)) || (pred.startsWith(rdf.NS)))) {
				// here we need to test if the property belongs to the RDF or RDF-Schema namespace.
				RDF_Property_test(pred);
	}

	// the subject
		  subject = existing.get(subj);
	if (subject == null) {
		subject = new Resource(subj);
		subj_int = existing.put(subj, subject);
	} else {
			 subj_int = existing.get_int(subj);
		  }

	if (res) { // the object is a Resource and not a Literal
					 // System.out.println("entering object as a resource");
					 object = existing.get(obj);
		if (object == null) {
			object = new Resource(obj);
			obj_int = existing.put(obj, object);
		} else {
						obj_int = existing.get_int(obj);
					 }

		// In case the predicate of the statement starts with the RDF-Schema namespace.
		if (pred.startsWith(rdfschema.NS)) {
			if (pred.equals(rdfschema.subClassOf)) enter_subClassOf(subject, object, subj, obj);
			if (pred.equals(rdfschema.subPropertyOf)) enter_subPropertyOf(subject, object, subj, obj);
			if (pred.equals(rdfschema.range)) enter_domain_range(2, subject, object, subj, obj);
			if (pred.equals(rdfschema.domain)) enter_domain_range(1, subject, object, subj, obj);
			if (pred.equals(rdfschema.seeAlso)) enter_sA_iDB_C_L_V(1, subject, subj, obj_lit, obj_int);
			if (pred.equals(rdfschema.isDefinedBy)) enter_sA_iDB_C_L_V(2, subject, subj, obj_lit, obj_int);
			if (pred.equals(rdfschema.comment) ||
				 pred.equals(rdfschema.label)) e.emit_error(3, 19, statement, "Model.addStatement");
		} // end rdfschema.NS

		// In case the predicate of the statement starts with the RDF namespace.
		if (pred.startsWith(rdf.NS)) {
			if (pred.equals(rdf.type)) enter_type(subject, subj, obj);
			if (pred.equals(rdf.subject)) enter_s_p_o(1, subject, object, subj, obj);
			if (pred.equals(rdf.predicate)) enter_s_p_o(2, subject, object, subj, obj);
			if (pred.equals(rdf.object)) enter_s_p_o(3, subject, object, subj, obj);
			if (pred.equals(rdf.value)) enter_sA_iDB_C_L_V(5, subject, subj, obj_lit, obj_int);
			if (pred.startsWith(rdf.msp)) {
                            test_msp(pred);
                            enter_msp(subject, subj, new Integer(obj_int));
                        }
		}


	// Object is a Literal
	} else {
		if (pred.startsWith(rdfschema.NS)) {
			if (pred.equals(rdfschema.subClassOf) ||
				 pred.equals(rdfschema.subPropertyOf) ||
				 pred.equals(rdfschema.range) ||
				 pred.equals(rdfschema.domain)) e.emit_error(3, 20, statement, "Model.addStatement");
			if (pred.equals(rdfschema.comment)) enter_sA_iDB_C_L_V(3, subject, subj, obj_lit, -1);
			if (pred.equals(rdfschema.label)) enter_sA_iDB_C_L_V(4, subject, subj, obj_lit, -1);
			if (pred.equals(rdfschema.seeAlso) ||
				 pred.equals(rdfschema.isDefinedBy)) e.emit_error(3, 20, statement, "Model.addStatement");

		}
		if (pred.startsWith(rdf.NS)) {
			if (pred.equals(rdf.type) ||
				 pred.equals(rdf.subject) ||
				 pred.equals(rdf.predicate)) e.emit_error(3, 20, statement, "Model.addStatement");
			if (pred.equals(rdf.object)) enter_s_p_o(3, subject, obj_lit, subj, obj);
			if (pred.equals(rdf.value)) enter_sA_iDB_C_L_V(5, subject, subj, obj_lit, -1);
			if (pred.startsWith(rdf.msp)) {
                          test_msp(pred);
                          enter_msp(subject, subj, obj_lit);
                        }
		} // end rdf.NS

	}
	// insert the link
	if (! (pred.startsWith(rdfschema.NS) || pred.startsWith(rdf.NS))) {
					 predicate = existing.get(pred);
		if (! (predicate == null)) {
			if (predicate instanceof RDF_Property) {
				rdf_property = (RDF_Property)predicate;
				if (res) rdf_property.addlink(subj_int, obj_int); else rdf_property.addlink(subj_int, obj_lit);
				// System.out.println("!!!pred: "+pred+" subj: "+subj+" obj: "+obj);
			} else { e.emit_error(3, 23, statement, "Model.addStatement"); }
		} // we do not need the else part here since we enter every predicate in the beginning
	}
	//System.out.println("out addStatement");
	} // end addStatement

      private void test_msp(String pred) {
        String s = pred.substring(rdf.msp.length(),pred.length());
        if (s.startsWith("0")) e.emit_error(3,100,"no leading zero allowed for container members", "Model.test_msp");
        try {
          Integer I = new Integer(s);
          if (I.intValue()<=0) e.emit_error(3,100,"must be greater than zero", "Model.test_msp");
        } catch (Exception ex) {
          e.emit_error(3,100,"must be an Integer", "Model.test_msp");
        }
      }

	/*
	 * Added on 02. August 2001 by Karsten Tolle
	 * API methodes needed to work on the model. (At least needed for the Validator.)
	 * 1. getNodes() returning a Collection containing all the values of the existing HashMap
	 * 2. contains(String URI) returns a boolean weather the resource having the specified URI is contained by the model
	 * 3. getResource(String URI) returns the resource with the specified URI
	 *
	 * Further methodes for a convinient and usefull for usage:
	 * 4. getClasses() returning a Collection of all classed contained by the model
	 * 5. getProperties() returning a Collection of all properties contained by the model
	 * added by Sofia
	 * getDataResources()
	 * ... ?
	 * 6. contains(String pred, String sub, String obj) returning a boolean weather the statement contained by the model
	 * 7. remove(String pred, String sub, String obj) removing the statement from the model
	 */



	 /**
	  * Returning a Collection containing all the values of the existing HashMap.
	  */
	  public Collection getNodes() {
	  	Collection c = existing.values();
		return c;
	  }

	 /**
	  * Returns a boolean weather the resource having the specified URI is contained by the model.
	  */
	  public boolean contains(String URI) {
		  boolean b = existing.containsKey(URI);
		  return b;
	  }

	 /**
	  * Returns the resource with the specified URI.
	  */
	  public Resource getResource(String URI) {
		  Resource r = (Resource)existing.get(URI);
		  return r;
	  }

			 public Resource getResource(int i) {
              Resource r = (Resource)existing.get(i);
              return r;
          }


	 /**
	  * Returning a Collection of all classes contained by the model.
	  */
	  public Collection getClasses() {
		Collection ex = existing.values();
		Collection c = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
				Object next = it.next();
				if (next instanceof RDF_Class) {
					c.add(next);
				}
		}
		return c;
	  }

	 /**
	  * Returning a Collection of all metaclasses contained by the model.
	  */
	  public Collection getAllMetaClasses() {
		Collection ex = existing.values();
		Collection mc = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
				Object next = it.next();
				if (next instanceof RDF_MetaClass) {
					mc.add(next);
				}
		}
		return mc;
	  }

	 /**
	  * Returning a Collection of all metaclasses of classes contained by the model.
	  */
	  public Collection getMetaClasses() {
		Collection ex = existing.values();
		Collection mc = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
				Object next = it.next();
				if ( (next instanceof RDF_MetaClass) ) {
					if ( ((RDF_MetaClass)next).getKind() == RDF_MetaClass.META_CLASS)
						mc.add(next);
				}
		}
		return mc;
	  }

	/**
	  * Returning a Collection of all metaclasses of properties contained by the model.
	  */
	  public Collection getMetaProperties() {
		Collection ex = existing.values();
		Collection mc = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
				Object next = it.next();
				if ( (next instanceof RDF_MetaClass) ) {
					if ( ((RDF_MetaClass)next).getKind() == RDF_MetaClass.META_PROPERTY)
						mc.add(next);
				}
		}
		return mc;
	  }

	 /**
	  * Returning a Collection of all properties contained by the model.
	  */
	  public Collection getProperties() {
		Collection ex = existing.values();
		Collection c = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
	        	Object next = it.next();
	        	if (next instanceof RDF_Property) {
					c.add(next);
				}
			  }
		return c;
	  }

    /**
	  * Returning a Collection of all reified statements contained in the model.
	  */
	  public Collection getReifiedStatements() {
	  	Collection ex = existing.values();
		Collection c = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
				Object next = it.next();
				if (next instanceof RDF_Statement) {
	        		c.add(next);
				}
	        }
		return c;
	  }

	 /**
	  * Returning a Collection of all RDF containers contained in the model.
	  */
	  public Collection getContainers() {
	  	Collection ex = existing.values();
	  	Collection c = new ArrayList();
		for (Iterator it = ex.iterator(); it.hasNext(); ) {
				Object next = it.next();
				if (next instanceof RDF_Container) {
					c.add(next);
				}
			  }
	  	return c;
	  }

	 /**
     *  Returns a Collection of all resources that don't belong
	  *  to the basic RDF types i.e., rdfs:Class, rdf:Property, rdf:Container and
     *  rdf:Statement.
	  */
	  public Collection getDataResources() {
	  	Collection ex = existing.values();
		Collection c = new ArrayList();
	  	for (Iterator it = ex.iterator(); it.hasNext(); ) {
        	Object next = it.next();
			if ( !(next instanceof RDF_Class) && !(next instanceof RDF_Property) &&
				  !(next instanceof RDF_Statement) && !(next instanceof RDF_Container)) {
					c.add(next);
				}
	        }
		return c;
	  }

	 /**
	  * Returning a boolean whether the statement contained by the model.
	  */
	  public boolean contains(String pred, String sub, String obj) {
		boolean b = false;
		if (! this.contains(pred)) return false;
                int sub_int, obj_int;
					 sub_int = existing.get_int(sub);
					 obj_int = existing.get_int(obj);
		Resource r = this.getResource(pred);
		if (r instanceof RDF_Property) {
			RDF_Property p = (RDF_Property)r;
			if (p.link_contains(sub_int, obj_int)) return true;
		}
		// if r is not a RDF_Property the statement is not contained by the model
		return false;
	  }

	 /**
	  * Returning a boolean whether the statement contained by the model.
	  */
	  public boolean contains(String pred, String sub, Literal obj) {
		boolean b = false;
		if (! this.contains(pred)) return false;
					 int sub_int;
					 sub_int = existing.get_int(sub);
		Resource r = this.getResource(pred);
		if (r instanceof RDF_Property) {
			RDF_Property p = (RDF_Property)r;
			if (p.link_contains(sub_int, obj)) return true;
		}
		// if r is not a RDF_Property the statement is not contained by the model
		return false;
	  }

	/**
	 * Returning a HashMap containing the URI and the object reference of
	 * all the external namespaces that have been parsed.
	 */
	public HashMap getNamespaces() {
		return namespaces;
	}

	 /**
	  * Will be called by the parser if he reached the EOF of the current file. The explicit stated namespaces are inside the Array List.
	  * The idea is to include everything in advance and do not allow to fetch during validation to provide a determinitic result of the
	  * validator.
	  * new since 08. Aug 2001 entered by Karsten Tolle
	  */
	 public void fetch_all(ArrayList ex_ns, parser par) {
		// we now want to connect to the namespaces in the array list and include all triples contained by them.
	 String baseURI = BaseURI;
		for (Iterator i = ex_ns.iterator(); i.hasNext(); ) {
			String ns = i.next().toString();
		if ( !ns.equals("") ) {
			  // the ending '#' need to be cutted for connecting
			  if (ns.endsWith("#")) {
				  int j = ns.length();
				  ns = ns.substring(0,--j);
			}
			fetch_all_ns(ns, par);
		}
		}
		//Because BaseURI may have been set URIs of the external NS
	  BaseURI = baseURI;
	  }

	private void fetch_all_ns(String ns, parser par) {
		String nsURI = ns;
		if ( ns.concat("#").equals(rdfschema.NS)) {
			ns = myrdfschemaXML;
			nsURI = rdfschema.NS;
		}
		if ( ns.concat("#").equals(rdf.NS)){
			ns = myrdfXML;
			nsURI = rdf.NS;
		}
		if ( ns.concat("#").equals(XMLSchema_DT.NS)){
			nsURI = XMLSchema_DT.NS;
			if (namespaces.get(nsURI) == null)  {
				namespaces.put(nsURI, new Namespace(nsURI));
			}
			return;
		}
		if (! done_list.contains(nsURI) ) {
			done_list.add(nsURI);
			// we need to connect to the namespace and enter the model to the model_list
			if (verbose) System.out.println("we need to connect to: "+ns);
			try {
				parser p = new parser(ns, this);
				// the new parser should have the same options than the old
				p.setonly(par.getonly());
				p.settriples(par.gettriples());
				p.setsimple(par.getsimple());
				p.setfetch_all(par.getfetch_all());
				p.setverbose(par.getverbose());
				p.setdebug(par.getdebug());
				p.parse();
				// if there is an error in connetion to the namespace
				if (p.error_count > 0) {
					if (verbose) System.err.println("error in constr: "+ns);
				} else {
					if (verbose) System.out.println("Namespace "+ns+" added to the model");
					if (!nsURI.endsWith("#")) {
						nsURI = nsURI.concat("#");
					}
					namespaces.put(nsURI, new Namespace(nsURI));
					//System.out.println("add namespace " + nsURI) ;
				}
			} catch (Exception e) {
				System.err.println(e);
			} // end of try
		} // end if
	 }

	/**
	 * Try to get all information of RDF_Properties and RDF_Classes
	 * we entered to the Model.
	 */
	public void fetch() {
		// We need to create an extra list out of the Collection
		// otherwise Java would throw a 'ConcurrentModificationException'
		ArrayList valset = new ArrayList();
		Collection valset1 = this.getNodes();
		for (Iterator it = valset1.iterator(); it.hasNext(); ) {
			valset.add(it.next());
		}
		for (int i=0; i<valset.size(); ) {
			Object value = valset.get(i++);
			if (value instanceof RDF_Property || value instanceof RDF_Class) {
				RDF_Resource rdf_resource = (RDF_Resource)value;
				String s = rdf_resource.getID();
				if (s.startsWith(rdfschema.NS) || s.startsWith(rdf.NS)) {
				} else this.fetch(s);
			}
		}
		while (! valset1.containsAll(this.getNodes())) { fetch(); } // recursive call until we have no changes
	}





	/**
	 * In the case the URI belongs to a namespace, we try to get the information
	 * about URI and enter them to our basis_model.
	 * Moved from Validator to the Model 03. Aug. 2001 by KT
	 */
	public void fetch(String URI) {
		boolean neic = true; // no error in connection
		if ((! done_list.contains(URI)) && (! URI.startsWith(XMLSchema_DT.NS))) {
		ArrayList while_list = new ArrayList();
		while_list.add(URI);
		while (! while_list.isEmpty()) {
			String next = while_list.get(0).toString();
			while_list.remove(0);
			// System.out.println("in fetch_info after remove");
			if (next.startsWith(getBaseURI())) {
			// we should have all info
			// System.out.println("got everything");
			} else {
			int j = next.indexOf("#");
			if (j <= 0) {
				// System.out.println("Warning: no ancher!!! for "+next);
			} else {
				Model ns_model = null;
				String ns = next.substring(0,j);
				// System.out.println("NS for "+next+" is "+ns);
				if (model_list.containsKey(ns)) {
				// we already parsed the namespace and have the model in the model_list
				// so there is nothing to do here than set the ns_model
					ns_model = (Model)model_list.get(ns);
				} else {
				// we need to connect to the namespace and enter the model to the model_list
					try {
						parser p = new parser(ns); // all options will be turned off
						// if there is an error in connetion to the namespace
						if (p.error_count > 0) {
							// System.out.println("error in constr.");
							neic = false;
						} else {
							Object result = p.parse().value;
							if (result instanceof Model) {
								ns_model = (Model)result;
								model_list.put(ns, ns_model);
							} else {
								e.emit_error(3, 44, "No model returned!", "Model.fetch_information");
							 }
						}
					} catch (Exception e) {
						System.err.println(e);
					}
				}
				// now we are sure that the model_list contains the model we need
				// query Statements about the property/class and enter them to the 'basis_model'
				// a list of new subPropertyOf/subClassOf will be returned
				if (neic) {
					ArrayList al = ns_model.getandadd(this, next, ns);
					for (int k = 0; k<al.size(); ) {
					String super_elem = al.get(k++).toString();
					// not entering elements of the RDF or RDF Schema
					// to the 'while_list'
					// bug-fix: 15.12.1999 by Karsten Tolle
					if (! (done_list.contains(super_elem) ||
						super_elem.startsWith(rdfschema.NS) ||
						super_elem.startsWith(rdf.NS)))
							while_list.add(super_elem);
					}
				}
			}
			done_list.add(next);
			} // now we got all infos
		} //end while
		} // end if fetch
	} // end fetch_information



	 /**
	  * If <pred> is not already entered to the model as a Property it will be done
	  * by this method.
	  */
	 private int enter_Property(String pred) {
	RDF_Property rdf_property;
		  int pred_int = 0;
		  Object predicate = existing.get(pred);
	if (! (predicate == null)) {
		if (predicate instanceof RDF_Class) {
			e.emit_error(3, 1, pred, "Model.enter_Property");
		} else {
			if (predicate instanceof RDF_Resource) {
				if (!(predicate instanceof RDF_Property)) {
					rdf_property = new RDF_Property((RDF_Resource)predicate);
					// unres_Properties.add(pred);
					pred_int = existing.put(pred, rdf_property);
				}
			} else { // it is a Resource
				rdf_property = new RDF_Property(pred);
				// unres_Properties.add(pred);
				pred_int = existing.put(pred, rdf_property);
			}
		}
		// System.out.println("Predicate exists: "+pred);
	} else {
		rdf_property = new RDF_Property(pred);
		// unres_Properties.add(pred);
		pred_int = existing.put(pred, rdf_property);
					 if (pred.startsWith(rdf.NS + "_")) {
						  // we want to enter the implicit information here that
						  // ContainerMembershipProperties are sub properties of
						  // the property rdfs:member.
						  addStatement(rdfschema.subPropertyOf, pred, rdfschema.member);
					 }
	}
        return pred_int;
	 }

    /**
     * Testing in the case that <str> starts with RDF or RDF-Schema namespace
	  * if they belong to the namespace.
     */
    private void RDF_test(String str) {
	// testing if str belong to RDF-Schema namespace
	// the empty string is ok
	if (str.startsWith(rdfschema.NS))
		if (!(  rdfschema.all.contains(str) )) {
				int i = str.indexOf("#");
				if (str.length() <= ++i) return; // empty string
				 e.emit_error(3, 25, str, "Model.RDF_test");
		}
	// testing if str belong to RDF namespace
	if (str.startsWith(rdf.NS))
		if (!(	rdf.Classes.contains(str) ||
			rdf.Properties.contains(str) ||
	      str.startsWith(rdf.msp) || str.equals(rdf.nil) )) {
				int i = str.indexOf("#");
				if (str.length() <= ++i) return; // empty string, index starting at zero therefore we need to increment first
					 e.emit_error(3, 26, str, "Model.RDF_test");
		 }
	 }

    /**
	  * Testing in the case that <pred> starts with RDF or RDF-Schema namespace
     * if they belong to the namespace and is a Property.
     */
    private void RDF_Property_test(String pred) {
	if (pred.startsWith(rdfschema.NS))
	   // Test if the property belong to the Schema_NS.
		if (! rdfschema.Properties.contains(pred)) e.emit_error(3, 25, pred, "Model.RDF_Property_test");
	if (pred.startsWith(rdf.NS))
		// Test if the property belong to the RDF_NS.
		if (! (rdf.Properties.contains(pred) ||
				  pred.startsWith(rdf.msp) )) e.emit_error(3, 26, pred, "Model.RDF_Property_test");
	 }


	 /**
     * Entering a subPropertyOf statement to the <subject> and making a Propery out of the <object>.
	  * Method for properties having domain = rdf:Property and range = rdf:Property.
     */
    private void enter_subPropertyOf(Object subject, Object object, String subj, String obj) {
    	modification_extention_check("subPropertyOf", subj, obj);
	RDF_Property rdf_property, super_property;

	// The range of subPropertyOf is Property!
		  if (object instanceof RDF_Property) {
				super_property = (RDF_Property)object;
		  } else { super_property = make_property(obj); }

	if (subject instanceof RDF_Resource) {
		if (subject instanceof RDF_Class) e.emit_error(3, 1, subj, "Model.enter_subPropertyOf");
		if (subject instanceof RDF_Statement) e.emit_error(3, 8, subj, "Model.enter_subPropertyOf");
		if (subject instanceof RDF_Container) e.emit_error(3, 11, subj, "Model.enter_subPropertyOf");
		if (subject instanceof RDF_Property) {
			rdf_property = (RDF_Property)subject;
		} else {
			// unres_Properties.add(subj);
			rdf_property = new RDF_Property((RDF_Resource)subject);
			existing.put(subj, rdf_property);
		}
	} else { // subject must be Resource
		// unres_Properties.add(subj);
		rdf_property = new RDF_Property((Resource)subject);
		existing.put(subj, rdf_property);
	}
		  rdf_property.addsubPropertyOf(super_property);
    }

    /**
     * Entering a subClassOf statement to the <subject> and making a Class out of the <object>.
     * Method for properties having domain = rdfs:Class and range = rdfs:Class.
	  */
	 private void enter_subClassOf(Object subject, Object object, String subj, String obj) {
		modification_extention_check("subClassOf", subj, obj);
	RDF_Class rdf_class, rdf_super_class;
	// The range of subClassOf is Class, so, we enter this information here.
	if (object instanceof RDF_Class) {
		rdf_super_class = (RDF_Class)object;
	} else {
		rdf_super_class = make_class(obj);
	}
	if (subject instanceof RDF_Resource) {
		if (subject instanceof RDF_Property) e.emit_error(3, 4, subj, "Model.enter_subClassOf");
		if (subject instanceof RDF_Statement) e.emit_error(3, 7, subj, "Model.enter_subClassOf");
		if (subject instanceof RDF_Container) e.emit_error(3, 10, subj, "Model.enter_subClassOf");
		if (subject instanceof RDF_Class) {
			rdf_class = (RDF_Class)subject;
		} else { // only RDF_Resource
			rdf_class = new RDF_Class((RDF_Resource)subject);
			existing.put(subj, rdf_class);
		}
	} else { // subject must be Resource
		rdf_class = new RDF_Class((Resource)subject);
		// unres_Classes.add(subj);
		existing.put(subj, rdf_class);
	}
        rdf_class.addsubClassOf(rdf_super_class);
    }

	 /**
	  * To infer the type of the given classname for all instances of its subclasses (recursive).
	  * Will be used as an optional feature, at the beginning only for rdfs:Class and
	  * rdf:Property only.
	  */
	 public void infer() {
		infer(rdfschema.Class);
		infer(rdf.Property);
		infer(rdfschema.Container);
		infer(rdf.Statement);
		System.out.println("done");
	 }

	 private void infer(String classname) {
		//System.out.println("infer started with: "+classname);
		HashSet subclasses = get_subClassesOf((RDF_Class)existing.get(classname));
		/*for (Iterator i = subclasses.iterator(); i.hasNext(); ) {
			 String s = i.next().toString();
			 System.out.println("subclasses of Class: "+s);
		}*/
		if (subclasses.size() <= 0) return;
		Collection nodes = this.getNodes();
		for (Iterator it = nodes.iterator(); it.hasNext(); ) {
				Object o = it.next();
				if (o instanceof RDF_Resource) {
				  RDF_Resource res = (RDF_Resource)o;
				  ArrayList al = res.gettype();
				  for (Iterator it2 = al.iterator(); it2.hasNext(); ) {
						RDF_Class rdf_class = (RDF_Class)it2.next();
						if (subclasses.contains(rdf_class)) {
//                      System.out.println("inherit type: "+classname+" for "+res.getID());
							 this.addStatement(rdf.type, res.getID(), classname);
							 break; // we do not need to go on here
						}
				  }
			 }
		}
	}

	/**
	 * Returns a HashSet containing all sub classes of the given class.
	 */
	private HashSet get_subClassesOf(RDF_Class classname) {
		HashSet s = new HashSet();
		HashSet h = new HashSet();
		HashSet h1 = new HashSet();
		h.add(classname);
		Collection classes = this.getClasses();
		do {
		  h1.addAll(h);
		  for (Iterator it = classes.iterator(); it.hasNext(); ) {
		  RDF_Class c = (RDF_Class)it.next();
			 ArrayList sco = c.getsubClassOf(); // ArrayList of RDF_Classes
					 for (Iterator it2 = sco.iterator(); it2.hasNext(); ) {
						  RDF_Class rdf_class = (RDF_Class)it2.next();
						  if (h.contains(rdf_class)) {
							  /*Bug-fix: 23.01.2003 by Sofia Alexaki: Object reference,
								  not URI should be added in the HashSets  */
								s.add(c);
								h.add(c);
						  }
					 }
		  }
		} while (! h1.containsAll(h)); //repeat until nothing changes any more
		return s;
	 }

	 /**
	  * This method will test if modifications or extentions are made to subjects not contained by the current namespace.
	  * The method is called whenever a domain, range, subClass or subProperty is defined. In this cases it can result in
	  * semanicaly problems and we want to be sure that the user realizes this problem. Therefore a warning will be generated.
	  */
    private void modification_extention_check(String prop, String subj, String obj) {
		if (subj.startsWith(BaseURI)) return;
		  if (BaseURI.equals(myrdfschemans+"#")) return;
		  if (BaseURI.equals(myrdfns+"#")) return;
	if (BaseURI.equals(rdfschema.NS)) return; // we assume the rdf schema namespace to be valid
	if (getandadd) return; // for generated models we presented this warning already
        // implicit sub property setting for cmp.
		  if (prop.equals("subPropertyOf") && subj.startsWith(rdf.NS+"_") && obj.equals(rdfschema.member)) return;
	e.emit_warning("In the namespace "+BaseURI+" you want to extend or modify the resource "+subj+" by entering a new "+prop+" with the value "+obj+".", "Model.modification_extention_check");
	 }


	 /**
	  * Entering a domain (1) or range (2) statement to the <subject> and making a Class out of the <object>.
	  * Method for properties having domain = rdf:Property and range = rdfs:Class.
	  */
	 private void enter_domain_range(int i, Object subject, Object object, String subj, String obj) {
		if (i==1) modification_extention_check("domain", subj, obj);
		if (i==2) modification_extention_check("range", subj, obj);
		  RDF_Property rdf_property;
		  RDF_Class domain_range;
		  // The range of domain is Class!
	if (object instanceof RDF_Class) {
				domain_range = (RDF_Class)object;
		  } else { domain_range = make_class(obj); }

	if (subject instanceof RDF_Resource) {
		if (subject instanceof RDF_Class) e.emit_error(3, 1, subj, "Model.enter_domain_range");
		if (subject instanceof RDF_Statement) e.emit_error(3, 8, subj, "Model.enter_domain_range");
		if (subject instanceof RDF_Container) e.emit_error(3, 11, subj, "Model.enter_domain_range");
		if (subject instanceof RDF_Property) {
			rdf_property = (RDF_Property)subject;
		} else { // only RDF_Resource
			// unres_Properties.add(subj);
			rdf_property = new RDF_Property((RDF_Resource)subject);
			existing.put(subj, rdf_property);
		}
	} else {
		// unres_Properties.add(subj);
		rdf_property = new RDF_Property((Resource)subject);
		existing.put(subj, rdf_property);
	}
		  if (i == 1) rdf_property.adddomain(domain_range);
			if (i == 2) rdf_property.addrange(domain_range);
	 }


	 /**
	  * Entering a seeAlso (1), isDefinedBy (2), comment (3),
	  * label (4), value (5) statement to the <subject>.
	  */
	 private void enter_sA_iDB_C_L_V(int i, Object subject, String subj, Literal obj, int obj_int) {
	if (subject instanceof RDF_Resource) {
		RDF_Resource rdf_resource;
		rdf_resource = (RDF_Resource)subject;
		if (i == 1) rdf_resource.addseeAlso(obj_int);
		if (i == 2) rdf_resource.addisDefinedBy(obj_int);
		if (i == 3) rdf_resource.addcomment(obj);
		if (i == 4) rdf_resource.addlabel(obj);
		if (i == 5) {
                  if (obj_int > 0) rdf_resource.addvalue(obj_int);
                  else rdf_resource.addvalue(obj);
                }
	} else { // if subject is not a RDF_Resource it must be a Resource
		RDF_Resource rdf_resource = new RDF_Resource((Resource)subject);
		if (i == 1) rdf_resource.addseeAlso(obj_int);
		if (i == 2) rdf_resource.addisDefinedBy(obj_int);
		if (i == 3) rdf_resource.addcomment(obj);
		if (i == 4) rdf_resource.addlabel(obj);
		if (i == 5) {
                  if (obj_int > 0) rdf_resource.addvalue(obj_int);
                  else rdf_resource.addvalue(obj);
					 }
		existing.put(subj, rdf_resource);
	}
	 }

    /**
     * Entering a subject (1), predicate (2),
     * 		  object (3) statement to the <subject>.
     * The domain for these properties is rdf:Statement.
     * The range for prediate (2) is rdf:Property.
     */
    private void enter_s_p_o(int i, Object subject, Object object, String subj, String obj) {
	RDF_Statement rdf_statement;
        RDF_Property prop = null;
        if (i == 2) prop = make_property(obj);
	if (subject instanceof RDF_Resource) {
		if (subject instanceof RDF_Class) e.emit_error(3, 2, subj, "Model.enter_s_p_o");
		if (subject instanceof RDF_Property) e.emit_error(3, 5, subj, "Model.enter_s_p_o");
		if (subject instanceof RDF_Container) e.emit_error(3, 12, subj, "Model.enter_s_p_o");
		if (subject instanceof RDF_Statement) {
			rdf_statement = (RDF_Statement)subject;
			if (i == 1) if (! rdf_statement.setsubject(object))  e.emit_error(3, 31, obj, "Model.enter_s_p_o");
			if (i == 2) if (! rdf_statement.setpredicate(prop)) e.emit_error(3, 32, obj, "Model.enter_s_p_o");
			if (i == 3) if (! rdf_statement.setobject(object)) e.emit_error(3, 33, obj, "RDF_Statement.setobject");
		} else { // only RDF_Resource here we can have no error with existing values
			rdf_statement = new RDF_Statement((RDF_Resource)subject);
			if (i == 1) rdf_statement.setsubject(object);
			if (i == 2) rdf_statement.setpredicate(prop);
			if (i == 3) rdf_statement.setobject(object);
			existing.put(subj, rdf_statement);
		}
	} else { // here we can have no error with existing values
		rdf_statement = new RDF_Statement((Resource)subject);
		if (i == 1) rdf_statement.setsubject(object);
		if (i == 2) rdf_statement.setpredicate(prop);
		if (i == 3) rdf_statement.setobject(object);
		existing.put(subj, rdf_statement);
	}
    }


    /**
	  * Entering a member to the <subject> and make a RDF_Container out of it.
     */
    private void enter_msp(Object subject,String subj,Object obj) {
	RDF_Container rdf_container;
	if (subject instanceof RDF_Resource) {
		if (subject instanceof RDF_Property) e.emit_error(3, 6, subj, "Model.enter_msp");
		if (subject instanceof RDF_Statement) e.emit_error(3, 9, subj, "Model.enter_msp");
		if (subject instanceof RDF_Class) e.emit_error(3, 3, subj, "Model.enter_msp");
		if (subject instanceof RDF_Container) {
			rdf_container = (RDF_Container)subject;
			rdf_container.addmember(obj);
		} else { // only RDF_Resource
			rdf_container = new RDF_Container((RDF_Resource)subject);
			rdf_container.addmember(obj);
			existing.put(subj, rdf_container);
		}
	} else { // subject must be Resource
		rdf_container = new RDF_Container((Resource)subject);
		rdf_container.addmember(obj);
		existing.put(subj, rdf_container);
	}
    }


	 /**
     * Entering a type statement to the <subject> and making a Class out of the <object>.
     * In the case the <obj> is equal rdfs:Class or rdf:Property we cast the <subject> to
     * the corresponding class.
     */
    private void enter_type(Object subject, String subj, String obj) {
		  // the range of rdf:type is Class
	RDF_Class rdf_class = make_class(obj);
		  RDF_Resource rdf_resource;

        // System.out.println("end of enter_type");
		  //System.out.println("in enter_type");
	if (subject instanceof RDF_Resource) {
		rdf_resource = (RDF_Resource)subject;
	} else { // if subject is not a RDF_Resource it must be a Resource
		rdf_resource = new RDF_Resource((Resource)subject);
		existing.put(subj, rdf_resource);
	}
		  rdf_resource.addtype(rdf_class, existing);

        // If obj = rdfs:Class make a class out of subject
	if (obj.equals(rdfschema.Class)) {
		make_class(subj);
	}
	// If obj = rdf:Property make a property out of subject
	if (obj.equals(rdf.Property)) {
		make_property(subj);
		//System.out.println("make_property of "+subj);
	}
	// If obj = rdf:Statement make a Statement out of the subject.
	if (obj.equals(rdf.Statement)) make_statement(subj);

	// If obj = rdf:Bag make a Container out of the subject.
	if (obj.equals(rdf.Bag)) make_container(subj);
	// If obj = rdf:Seq make a Container out of the subject.
	if (obj.equals(rdf.Seq)) make_container(subj);
	// If obj = rdf:Alt make a Container out of the subject.
	if (obj.equals(rdf.Alt)) make_container(subj);

		  if (obj.equals(rdfschema.Container)) make_container(subj);
	 }

	 /**
	  * Making a Class out of the <object>.
	  */
	private RDF_Class make_class(String obj) {
	Object object = existing.get(obj);
		  RDF_Class rdf_class;
	if (object instanceof RDF_Resource) {
		if (! (object instanceof RDF_Class)) {
			if (object instanceof RDF_Property) e.emit_error(3, 4,  obj, "Model.make_class");
			if (object instanceof RDF_Statement) e.emit_error(3, 7, obj, "Model.make_class");
			if (object instanceof RDF_Container) e.emit_error(3, 10, obj, "Model.make_class");
			rdf_class = new RDF_Class((RDF_Resource)object);
			existing.put(obj, rdf_class);
		} else {
			rdf_class = (RDF_Class)object;
					 }
	} else { // object is only Resource
		rdf_class = new RDF_Class((Resource)object);
		existing.put(obj, rdf_class);
	}
		  return rdf_class;
	 }

	/**
	 * Making a MetaClass out of the <object>.
	 */
	private RDF_MetaClass makeMetaClass(RDF_Class rdf_class, int kind) {
		RDF_MetaClass metaClass = new RDF_MetaClass(rdf_class, kind);
		existing.put(metaClass.getID(), metaClass);
		return metaClass;
	}


	 /**
	  * Making a Property out of the <object>.
	  */
	 private RDF_Property make_property(String obj) {
	Object object = existing.get(obj);
		  RDF_Property rdf_property = null;
	if (object instanceof RDF_Resource) {
		if (! (object instanceof RDF_Property)) {
			if (object instanceof RDF_Class) e.emit_error(3, 1, obj, "Model.make_property");
			if (object instanceof RDF_Statement) e.emit_error(3, 8, obj, "Model.make_property");
			if (object instanceof RDF_Container) e.emit_error(3, 11, obj, "Model.make_property");
			rdf_property = new RDF_Property((RDF_Resource)object);
			existing.put(obj, rdf_property);
		} else {
			rdf_property = (RDF_Property)object;
		}
	} else { // object is only Resource
		rdf_property = new RDF_Property((Resource)object);
		existing.put(obj, rdf_property);
	}
        return rdf_property;
	 }

	 /**
	  * Making a Statement out of the <object>.
	  */
	 private void make_statement(String obj) {
	Object object = existing.get(obj);
	if (object instanceof RDF_Resource) {
		if (! (object instanceof RDF_Statement)) {
			if (object instanceof RDF_Class) e.emit_error(3, 2, obj, "Model.make_statement");
			if (object instanceof RDF_Property) e.emit_error(3, 5, obj, "Model.make_statement");
			if (object instanceof RDF_Container) e.emit_error(3, 12, obj, "Model.make_statement");
			RDF_Statement rdf_statement = new RDF_Statement((RDF_Resource)object);
			existing.put(obj, rdf_statement);
		}
	} else { // object is only Resource
		RDF_Statement rdf_statement = new RDF_Statement((Resource)object);
		existing.put(obj, rdf_statement);
	}
	 }

	 /**
	  * Making a Container out of the <object>.
     */
	 private void make_container(String obj) {
	Object object = existing.get(obj);
	if (object instanceof RDF_Resource) {
		if (! (object instanceof RDF_Container)) {
			if (object instanceof RDF_Class) e.emit_error(3, 3, obj, "Model.make_container");
			if (object instanceof RDF_Property) e.emit_error(3, 6, obj, "Model.make_container");
			if (object instanceof RDF_Statement) e.emit_error(3, 9, obj, "Model.make_container");
			RDF_Container rdf_container = new RDF_Container((RDF_Resource)object);
			existing.put(obj, rdf_container);
		}
	} else { // object is only Resource
		RDF_Container rdf_container = new RDF_Container((Resource)object);
		existing.put(obj, rdf_container);
	}
    }

	 /**
     * Returns the statements comprising the model.
	  */
	  public ArrayList getStatements(){
      ArrayList statements = new ArrayList();
		RDF_Resource rdf_resource;
		RDF_Class rdf_class;
      RDF_Property rdf_property;
      RDF_Statement rdf_statement;
		Resource r;

		Collection valset = existing.values();
		boolean isResource = false;
      Object o;
      Literal l;
      for (Iterator it = valset.iterator(); it.hasNext(); ) {
			 Object value = it.next();
				  if (value instanceof RDF_Resource) {
						rdf_resource = (RDF_Resource)value;
						ArrayList list = rdf_resource.getcomment();
                  for (int i=0; i<list.size(); ) {
							 l = (Literal)list.get(i++);
							 // the range of rdfs:comment is Literal
                      statements.add(new Triple(rdfschema.comment, rdf_resource.getID(), l));
                  }
                  list = rdf_resource.getlabel();
						for (int i=0; i<list.size(); ) {
                      l = (Literal)list.get(i++);
                      // the range of rdfs:label is Literal
							 statements.add(new Triple(rdfschema.label, rdf_resource.getID(), l));
						}
						list = rdf_resource.getseeAlso();
						for (int i=0; i<list.size(); ) {
							 r = (Resource)list.get(i++);
                      // range of seeAlso is Resource
							 statements.add(new Triple(rdfschema.seeAlso, rdf_resource.getID(), r.getID()));
						}
                  list = rdf_resource.getisDefinedBy();
						for (int i=0; i<list.size(); ) {
                      r = (Resource)list.get(i++);
                      // range of is DefinedBy is Resource
                      statements.add(new Triple(rdfschema.isDefinedBy, rdf_resource.getID(), r.getID()));
                  }
                  list = rdf_resource.getvalue();
						for (int i=0; i<list.size(); ) {
							 o = list.get(i++);
							 if (o instanceof Resource) statements.add(new Triple(rdf.value, rdf_resource.getID(), ((Resource)o).getID()));
							 else statements.add(new Triple(rdf.value, rdf_resource.getID(), (Literal)o));
                  }
						list = rdf_resource.gettype();
                  for (int i=0; i<list.size(); ) {
							 r = (Resource)list.get(i++);
							 // range of is type is Class -> Resource
							 statements.add(new Triple(rdf.type, rdf_resource.getID(), r.getID()));
                  }
		}
		if (value instanceof RDF_Class) {
						  rdf_class = (RDF_Class)value;
						  ArrayList list = rdf_class.getsubClassOf();
						  for (int i=0; i<list.size(); ) {
								RDF_Class obj_class = (RDF_Class)list.get(i++);
                        statements.add(new Triple(rdfschema.subClassOf, rdf_class.getID(), obj_class.getID()));
                    }
		}
		if (value instanceof RDF_Property) {
						  rdf_property = (RDF_Property)value;
						  ArrayList list = rdf_property.getsubPropertyOf();
						  for (int i=0; i<list.size(); ) {
                        r = (Resource)list.get(i++);
                        statements.add(new Triple(rdfschema.subPropertyOf, rdf_property.getID(), r.getID()));
						  }
						  list = rdf_property.getdomain();
						  for (int i=0; i<list.size(); ) {
								r = (Resource)list.get(i++);
                        statements.add(new Triple(rdfschema.domain, rdf_property.getID(), r.getID()));
                    }
						  list = rdf_property.getlink();
                    for (int i=0; i<list.size(); ) {
								Link link = (Link)list.get(i++);
                        o = link.getobject();
								r = (Resource)link.getsubject();
								if (! (o instanceof Literal)) {
                            Resource obj = (Resource)o;
									 statements.add(new Triple(rdf_property.getID(), r.getID(), obj.getID()));
								} else {
                            l = (Literal)o;
									 statements.add(new Triple(rdf_property.getID(), r.getID(), l));
								}
                    }
                    list = rdf_property.getrange();
						  for (int i=0; i<list.size(); ) {
                        r = (Resource)list.get(i++);
								statements.add(new Triple(rdfschema.range, rdf_property.getID(), r.getID()));
                    }
		}
		if (value instanceof RDF_Statement) {
                    rdf_statement = (RDF_Statement)value;
                    if (rdf_statement.getsubject() != null) {
								r = (Resource)rdf_statement.getsubject();
								statements.add(new Triple(rdf.subject, rdf_statement.getID(), r.getID()));
						  }
						  if (rdf_statement.getpredicate() != null) {
								RDF_Property rdf_proptery = rdf_statement.getpredicate();
								statements.add(new Triple(rdf.predicate, rdf_statement.getID(), rdf_proptery.getID()));
						  }
						  if (rdf_statement.getobject() != null) {
                        o = rdf_statement.getobject();
								if (o instanceof Literal) {
                            l = (Literal)o;
                            statements.add(new Triple(rdf.object, rdf_statement.getID(), l));
								} else {
									 statements.add(new Triple(rdf.object, rdf_statement.getID(), ((Resource)o).getID()));
                        }
						  }
		}
		if (value instanceof RDF_Container) {
						  RDF_Container rdf_container = (RDF_Container)value;
						  ArrayList list = rdf_container.getmember();
                    for (int i=0; i<list.size(); ) {
							 int j = i;
                      j++;
							 o = list.get(i++);
                      if (o instanceof Resource) statements.add(new Triple(rdf.msp+j, rdf_container.getID(), ((Resource)o).getID()));
                      else statements.add(new Triple(rdf.msp+j, rdf_container.getID(), (Literal)o));
		    }
		}
	}
	return statements;
 }

	 /**
     * Prints the statements of this model.
     */
  public int printStatements() {
		int counter = 0;
      Triple t;
		Output put = new Output();
		ArrayList al = this.getStatements();
		for (Iterator i = al.iterator(); i.hasNext();){
        t = (Triple)i.next();
		  String object;
		  if (t.getObject() instanceof Literal) {
			 object = ((Literal)t.getObject()).getvalue();
        } else {
			 object = t.getObject().toString();
        }
		  ++counter;
        put.outln("Triple"+ counter +": "+t.getPredicate()+", "+t.getSubject()+", "+object, true);
      }
      return counter;
	}

	public int[] getStatistics() {
		String pred, subj, obj;
		RDF_Resource rdf_resource;
	   RDF_Class rdf_class;
		RDF_Property rdf_property;
		RDF_Statement rdf_statement;
      int tripleCounter = 0;
	   int classes = 0, extclasses = 0, properties = 0, extproperties = 0 ,
         containers = 0, statements = 0, resources = 0;
		Collection valset = existing.values();
	   for (Iterator it = valset.iterator(); it.hasNext(); ) {
		   Object value = it.next();
			if (value instanceof RDF_Resource) {
				rdf_resource = (RDF_Resource)value;
			   ArrayList list = rdf_resource.getcomment();
				for (int i=0; i<list.size(); ) {
					tripleCounter++;
               i++;
			   }
				list = rdf_resource.getlabel();
				for (int i=0; i<list.size(); ) {
					tripleCounter++;
                i++;
				}
			   list = rdf_resource.getseeAlso();
				for (int i=0; i<list.size(); ) {
               tripleCounter++;
					 i++;
				}
			list = rdf_resource.getisDefinedBy();
			for (int i=0; i<list.size(); ) {
               tripleCounter++;
					 i++;
			}
			list = rdf_resource.getvalue();
			for (int i=0; i<list.size(); ) {
				tripleCounter++;
             i++;
			}
			list = rdf_resource.gettype();
			for (int i=0; i<list.size(); ) {
             tripleCounter++;
				  i++;
			}
		}
		if (value instanceof RDF_Class) {
			rdf_class = (RDF_Class)value;
			ArrayList list = rdf_class.getsubClassOf();
			for (int i=0; i<list.size(); ) {
				tripleCounter++;
                                i++;
			}
         if (rdf_class.getID().startsWith(BaseURI))
 		      classes++;
			else
				extclasses++;
		}
		if (value instanceof RDF_Property) {
			rdf_property = (RDF_Property)value;
			ArrayList list = rdf_property.getsubPropertyOf();
			for (int i=0; i<list.size(); ) {
            tripleCounter++;
             i++;
			}
			list = rdf_property.getdomain();
			for (int i=0; i<list.size(); ) {
				tripleCounter++;
				 i++;
			}
			list = rdf_property.getlink();
			for (int i=0; i<list.size(); ) {
				Link link = (Link)list.get(i++);
            tripleCounter++;
			}
			if (rdf_property.getrange() != null) {
				tripleCounter++;
         }
			if (rdf_property.getID().startsWith(BaseURI))
  		      properties++;
         else
  		      extproperties++;
		}
		if (value instanceof RDF_Statement) {
			rdf_statement = (RDF_Statement)value;
			if (rdf_statement.getsubject() != null) {
				tripleCounter++;

			}
			if (rdf_statement.getpredicate() != null) {
				tripleCounter++;

			}
			if (rdf_statement.getobject() != null) {
				tripleCounter++;
			}
		statements++;
		}
		if (value instanceof RDF_Container) {
			RDF_Container rdf_container = (RDF_Container)value;
			ArrayList list = rdf_container.getmember();
			for (int i=0; i<list.size(); ) {
				int j = i;
				j++;
				tripleCounter++;
             i++;
			}
		containers++;
		}
	}
	  int j = this.existing.size();
	  resources = j - (classes + extclasses + properties + extproperties + containers + statements);
     int[] statistics = {tripleCounter, classes, extclasses, properties, extproperties, statements, containers, resources};
      for (int f=0; f<statistics.length; f++)
			if (verbose) System.out.println(statistics[f]);
      return statistics;
   };

 /** Prints the statistic containing the number of triples, classes, properties, containers, refeid statements and resources to the
  *  output stream declared in Output.
  */
  public void printStatistics() {
		int[] statistics = getStatistics();
      StringBuffer m = new StringBuffer();
		m.append("\nStatistics about triples, schema and data resources\n");
		m.append("------------------------------------------------------\n");
		m.append("\tNumber of triples "+ statistics[0] +"\n");
      m.append("\tNumber of Classes declared in this NS " + statistics[1]+ "\n");
		m.append("\tNumber of external Classes used in this NS " + statistics[2]+ "\n");
		m.append("\tNumber of Properties declared in this NS " + statistics[3]+ "\n");
		m.append("\tNumber of external Properties used in this NS " + statistics[4]+ "\n");
      m.append("\tNumber of Containers " + statistics[5]+ "\n");
      m.append("\tNumber of Reified Statements " + statistics[6]+ "\n");
      m.append("\tNumber of Resources (above resources are excluded) " + statistics[7]+ "\n");
      Output out = new Output();
		out.out(m.toString(), true);
	}

	 /** Whenever a system-generated identifier is needed for
      * statements or nodes.
      * (Should this generate a URI instead? Right now you can
		* use the getBaseURI() and combine it with the generated
      * System ID to get a URI for some internal model resources).
      */
    public String genSysID() {
		  // changed to take xml:base into account
	// String genid = getBaseURI()+"genID:"+anonymos;
		  String genid = "genID:"+anonymos;
	anonymos++;
	return genid;
    };

	 /** Set the base URI for the model. */
	public void setBaseURI(String bURI) {
	BaseURI = bURI;
        namespaces.put(bURI, new Namespace(bURI));
	 };

	 /** Get the base URI for the model. */
    public String getBaseURI() {
	   return BaseURI;
	 };

    /** Dump the content of the model and print it to the outputfile
		* defined in RDF_PAV/Main.
		*/
	public void dump() {
	StringBuffer buffer = new StringBuffer();
        ArrayList al;
		Output put = new Output();
		String pred, subj, obj;
		  Object o;
		  Literal l;
	put.out("\nThe classes of the Model: ", true);
	Collection valset = existing.values();
	for (Iterator it = valset.iterator(); it.hasNext(); ) {
		Object value = it.next();
		if (value instanceof RDF_Class) {
			RDF_Class rdf_class = (RDF_Class)value;
			buffer.append("\n"+rdf_class.getID());
								al = rdf_class.getsubClassOf();
			buffer.append("\n\tsubClassOf: ");
                        for (Iterator itsC = al.iterator(); itsC.hasNext();)
									 buffer.append(((Resource)itsC.next()).getID()+" ");
			buffer.append(rdf_res_dump((RDF_Resource)rdf_class));
			put.out(buffer.toString(), true);
			buffer.delete(0,buffer.length());
		}
	}

	put.out("\nThe properties of the Model: ", true);
	valset = existing.values();
	for (Iterator it = valset.iterator(); it.hasNext(); ) {
		Object value = it.next();
		if (value instanceof RDF_Property) {
			RDF_Property rdf_property = (RDF_Property)value;
			buffer.append("\n"+rdf_property.getID());
			al = rdf_property.getrange();
			buffer.append("\n\trange: ");
			for (Iterator itprop = al.iterator();itprop.hasNext();)
			  buffer.append(((Resource)itprop.next()).getID()+", ");
                        al = rdf_property.getdomain();
                        buffer.append("\n\tdomain: ");
                        for (Iterator itprop = al.iterator();itprop.hasNext();)
                            buffer.append(((Resource)itprop.next()).getID()+", ");
                        al = rdf_property.getsubPropertyOf();
                        buffer.append("\n\tsubPropertyOf: ");
                        for (Iterator itprop = al.iterator();itprop.hasNext();)
                              buffer.append(((Resource)itprop.next()).getID()+", ");
                        buffer.append("\n\tlinks: ");
			ArrayList list = rdf_property.getlink();
			for (int i=0; i<list.size(); ) {
				Link link = (Link)list.get(i++);
                                o = link.getobject();
                                Resource link_subj = (Resource)link.getsubject();
                                if (o instanceof Literal) {
                                  l = (Literal)o;
                                  buffer.append("("+link_subj.getID()+", "+l.toString()+") ");
                                } else {
                                  Resource obj_res = (Resource)o;
                                  buffer.append("("+link_subj.getID()+", "+obj_res.getID()+") ");
                                }
			}
			buffer.append(rdf_res_dump((RDF_Resource)rdf_property));
			put.out(buffer.toString(), true);
			buffer.delete(0,buffer.length());
		}
	}

	put.out("\nThe statements of the Model: ", true);
	valset = existing.values();
	for (Iterator it = valset.iterator(); it.hasNext(); ) {
		Object value = it.next();
		if (value instanceof RDF_Statement) {
			RDF_Statement rdf_statement = (RDF_Statement)value;
			buffer.append("\n"+rdf_statement.getID());
			buffer.append("\n\tpredicate: "+((RDF_Property)rdf_statement.getpredicate()).getID());
			buffer.append("\n\tsubject: "+((Resource)rdf_statement.getsubject()).getID());
								o = rdf_statement.getobject();
								if (o instanceof Literal) {
									 l = (Literal)o;
				 buffer.append("\n\tobject: "+l.toString());
								} else {
									 Resource obj_res = (Resource)o;
									 buffer.append("\n\tobject: "+obj_res.getID());
								}
			buffer.append(rdf_res_dump((RDF_Resource)rdf_statement));
			put.out(buffer.toString(), true);
			buffer.delete(0,buffer.length());
		}
	}

	put.out("\nThe containers of the Model: ", true);
	valset = existing.values();
	for (Iterator it = valset.iterator(); it.hasNext(); ) {
		Object value = it.next();
		if (value instanceof RDF_Container) {
			RDF_Container rdf_container = (RDF_Container)value;
			buffer.append("\n"+rdf_container.getID());
			buffer.append("\n\tmembers: "+rdf_container.getmember());
			buffer.append(rdf_res_dump((RDF_Resource)rdf_container));
			put.out(buffer.toString(), true);
			buffer.delete(0,buffer.length());
		}
	}

	put.out("\nThe rdf_resources of the Model: ", true);
	valset = existing.values();
	for (Iterator it = valset.iterator(); it.hasNext(); ) {
		Object value = it.next();
		if (value instanceof RDF_Resource && !(value instanceof RDF_Class ||
						       value instanceof RDF_Property ||
								 value instanceof RDF_Statement ||
								 value instanceof RDF_Container )){
			RDF_Resource rdf_resource = (RDF_Resource)value;
			buffer.append("\n"+rdf_resource.getID());
			buffer.append(rdf_res_dump(rdf_resource));
			put.out(buffer.toString(), true);
			buffer.delete(0,buffer.length());
		}
	}

	put.out("\nThe resources of the Model: ", true);
	 valset = existing.values();
	for (Iterator it = valset.iterator(); it.hasNext(); ) {
		Object value = it.next();
		if ((value instanceof Resource) && !(value instanceof RDF_Resource)) {
			Resource resource = (Resource)value;
			put.out("\n"+resource.getID(), true);
		}
	}
	}

	/**
	 * Returning the information of a RDF_Resource in a String.
	 */
	private String rdf_res_dump(RDF_Resource rdf_resource) {
	StringBuffer buffer = new StringBuffer();
		  buffer.append("\n\tcomment: ");
		  ArrayList al = rdf_resource.getcomment();
		  for (Iterator it = al.iterator(); it.hasNext();)
			buffer.append(((Literal)it.next()).getvalue()+", ");
		  al = rdf_resource.getlabel();
			buffer.append("\n\tlabel: ");
		  for (Iterator it = al.iterator(); it.hasNext();)
			buffer.append(((Literal)it.next()).getvalue()+", ");
		  al = rdf_resource.getseeAlso();
			buffer.append("\n\tseeAlso: ");
		  for (Iterator it = al.iterator(); it.hasNext();)
			buffer.append(((Resource)it.next()).getID()+", ");
		  al = rdf_resource.getisDefinedBy();
  		  buffer.append("\n\tisDefinedBy: ");
                  //System.out.println(rdf_resource.getID());
		  for (Iterator it = al.iterator(); it.hasNext();){
                        Object object = it.next();
                        //System.out.println("XX " +(Resource)object);
                        //System.out.println("ddddd" +((Resource)object).getID());
			buffer.append(((Resource)object).getID()+", ");

                   }
		  al = rdf_resource.getvalue();
		buffer.append("\n\tvalue: ");
		  for (Iterator it = al.iterator(); it.hasNext();) {
        		 Object next = it.next();
	    	         if (next instanceof Resource)
			     buffer.append(((Resource)next).getID()+", ");
			 else buffer.append( ((Literal)next).getvalue());
		  }
		  al = rdf_resource.gettype();
			buffer.append("\n\ttype: ");
		  for (Iterator it = al.iterator(); it.hasNext();)
			buffer.append(((Resource)it.next()).getID()+", ");
	return buffer.toString();
}
	 /**
	  * Get the information of the resource with the URI <about> from this.model
	  * and enter the statements to the <to_model>.model. The string <model_name>
	  * is just to give a richer error_message in the case of an error.
	  * Returns in case of a property the subPropertyOf list and in case
	  * of a class the subClassOfList.
	  */
	 private ArrayList getandadd(Model to_model, String about, String model_name) {
		to_model.getandadd = true;
	ArrayList return_list = new ArrayList();
	if (!(existing.containsKey(about))) {
		e.emit_error(3, 43, "Resource: "+about+" NS: "+model_name, "Model.getandadd");
		//System.out.println("The namespace "+model_name+" does not contain info about "+about+".");
	} else {
		Object object = existing.get(about);
		if (object instanceof RDF_Resource) {
			if (object instanceof RDF_Class) {
				RDF_Class rdf_class = (RDF_Class)object;
				return_list = getandadd_classinfo(rdf_class, to_model);
			} else {
				if (object instanceof RDF_Property) {
				// get the Property specific info
				RDF_Property rdf_property = (RDF_Property)object;
				return_list = getandadd_propertyinfo(rdf_property, to_model);
				} else {
				if (verbose) System.out.println("The element you search for is only a RDF_Resource.");
				}
			}
			// get the RDF_Resource specific info
			RDF_Resource rdf_resource = (RDF_Resource)object;
			getandadd_rdf_resourceinfo(rdf_resource, to_model);
		} else { if (verbose) System.out.println("The element you search for is only a Resource!"); }
	}
	// System.out.println("end getandadd");
	to_model.getandadd = false;
	return return_list;
    } // end getandadd

	  /**
	  * Get and enter the typical information of a RDF_Class for <rdf_class> and enter
	  * them to the model <model>. Still in use?? !!!
	  */
	 private ArrayList getandadd_classinfo(RDF_Class rdf_class, Model model) {
	ArrayList list = rdf_class.getsubClassOf();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.subClassOf, rdf_class.getID(), list.get(i++).toString());
	}
	return list; // containing the list of subClassOf statements
	 }


	 /**
	  * Get and enter the typical information of a RDF_Property for <rdf_class> and enter
	  * them to the model <model>. We are not entering the links at this position.
	  */
	 private ArrayList getandadd_propertyinfo(RDF_Property rdf_property, Model model) {
	 ArrayList list = rdf_property.getdomain();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.domain, rdf_property.getID(), list.get(i++).toString());
	}

	list = rdf_property.getrange();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.range, rdf_property.getID(), list.get(i++).toString());
	}

	list = rdf_property.getsubPropertyOf();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.subPropertyOf, rdf_property.getID(), list.get(i++).toString());
	}
	return list; // containing the list of subPropertyOf statements
	 }


	 /**
	  * Get and enter the typical information of a RDF_Resource for <rdf_class> and enter
	  * them to the model <model>.
	  */
	 private void getandadd_rdf_resourceinfo(RDF_Resource rdf_resource, Model model) {
	ArrayList list = rdf_resource.getcomment();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.comment, rdf_resource.getID(), (Literal)list.get(i++));
	}
	list = rdf_resource.getlabel();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.label, rdf_resource.getID(),  (Literal)list.get(i++));
	}
	list = rdf_resource.getseeAlso();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.seeAlso, rdf_resource.getID(), list.get(i++).toString());
	}
	list = rdf_resource.getisDefinedBy();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdfschema.isDefinedBy, rdf_resource.getID(), list.get(i++).toString());
	}
	list = rdf_resource.gettype();
	for (int i=0; i<list.size(); ) {
		model.addStatement(rdf.type, rdf_resource.getID(), list.get(i++).toString());
	}
	 }

	 public void solve_links() {
		  Collection c = existing.values(); // all resources we entered
		  for (Iterator i = c.iterator(); i.hasNext();){
			 Object o = i.next();
			 if (o instanceof RDF_Statement) {
				  ((RDF_Statement)o).solve_links(this.existing);
			 } else if (o instanceof RDF_Property) {
				  ((RDF_Property)o).solve_links(this.existing);
			 } else if (o instanceof RDF_Container) {
				  ((RDF_Container)o).solve_links(this.existing);
			 } else if (o instanceof RDF_Resource) {
				  ((RDF_Resource)o).solve_links(this.existing);
			 }

		  } // end for
	 }

	/**
	 * Casts the classes that are subclasses of the rdfs:Class/rdf:Property
	 * to RDF_MetaClass Objects.
	 */
	public void castToMetaClass() {
		castToMetaClass(0);
		castToMetaClass(1);
	}
	 /**
	  * Casts the classes that are subclasses of the rdfs:Class/rdf:Property
	  * to RDF_MetaClass Objects.
	  *@param i if <I> equals to 1 cast the subclasses of rdfs:Class to
	  *MetaClasses of classes. Otherwise it casts the subclasses of rdf:Property to
	  *MetaClasses of properties
	  */
	  private void castToMetaClass(int i) {
		  Resource res = null;
		  if (i == 0 )
			 res = getResource(rdfschema.Class);
		  else
			 res = getResource(rdf.Property);
		  if ( (res != null) && (res instanceof RDF_Class) ) {
			  RDF_Class topMetaClass = (RDF_Class)res;
			  HashSet subs = get_subClassesOf(topMetaClass);
			  subs.add(topMetaClass);
			  for (Iterator it = subs.iterator(); it.hasNext();){
				  Object o = it.next();
				  if (o instanceof RDF_Class) {
						RDF_Class rdf_class = (RDF_Class)o;
						if ( !(rdf_class instanceof RDF_MetaClass) ) {
							RDF_MetaClass metaclass = null;
							if (i == 0 )
								 metaclass = makeMetaClass(rdf_class, RDF_MetaClass.META_CLASS);
							else
								metaclass = makeMetaClass(rdf_class, RDF_MetaClass.META_PROPERTY);
							restoreClassMetaClassReference(rdf_class, metaclass);
					  }
				 }
		  }
	  }
  }

	private void restoreClassMetaClassReference(Resource resRef, Resource newResRef) {
		Resource resource = null;
		RDF_Resource rdf_resource = null;
		RDF_Class rdf_class = null;
		RDF_Property rdf_property = null;
		Object o;
		ArrayList list;
		Collection col = getNodes();
		HashSet valset = (new HashSet(col));
		for (Iterator it = valset.iterator(); it.hasNext(); ) {
			Object object = it.next();
			if (object instanceof RDF_Resource) {
				rdf_resource = (RDF_Resource)object;
				list = rdf_resource.gettype();
				if (list.contains(resRef)) {
						list.remove(resRef);
						rdf_resource.addtype( (RDF_Class)newResRef, this.existing);
				}
			}
			if (object instanceof RDF_Class) {
				rdf_class = (RDF_Class)object;
				list = rdf_class.getsubClassOf();
				if (list.contains(resRef)) {
					list.remove(resRef);
					rdf_class.addsubClassOf((RDF_Class)newResRef);
				}
			}
			if (object instanceof RDF_Property) {
				rdf_property = (RDF_Property)object;
				list = rdf_property.getdomain();
				if (list.contains(resRef)) {
					list.remove(resRef);
					rdf_property.adddomain((RDF_Class)newResRef);
				}
				list = rdf_property.getrange();
				if (list.contains(resRef)) {
					list.remove(resRef);
					rdf_property.addrange((RDF_Class)newResRef);
				}
			}
		}
	}


	/**
	 * Sets as superclass the class rdfs:Resource, if a class has no superclasses
	 * @param allClasses, Indicates if the supeclass will be added to
	 * all the classes of the model or to only the classes of the initial input file
	 */
	/*if the fetch_all is false then allClasses should be false  because it is
	  error to infer that a class without any superclass has as superclass the
	  rdfs:Resource.  Since in the namespace where it is defined it may be
	  subclass of the classes rdfs:Class, rdf:Property  */

	public void setResourceRoot(boolean allClasses) {
		Collection classes = this.getClasses();
		RDF_Class rdfs_resource = null;
		Resource object  = (Resource)this.getResource(rdfschema.Resource);
		Resource rdfsClass  = (Resource)this.getResource(rdfschema.Class);
		Resource rdfProperty  = (Resource)this.getResource(rdf.Property);
		//get rdfs:Reference
		if (object == null || !(object instanceof RDF_Class) ) {
			rdfs_resource = make_class(rdfschema.Resource);
		} else {
			rdfs_resource = (RDF_Class)object;
		}
		for (Iterator it = classes.iterator(); it.hasNext(); ) {
			RDF_Class cls = (RDF_Class)it.next();
			int ancs = cls.getsubClassOf().size();
			//Note: When namespace class to test cls not belong in the rdf/s namespaces
			if  ( (ancs == 0) && (cls != rdfsClass) && (cls != rdfProperty) && (cls != rdfs_resource))  {
				if (allClasses || (!allClasses && cls.getID().startsWith(getBaseURI()) )  ) {
					cls.addsubClassOf(rdfs_resource);
				}
			}
		}
	}

  /**
   * The resources are classified in the namespace where are defined.
   * Note It may be more efficient to be classified during model parsing,
   * problem with about attribute you should again use string.startsWith
   */
  private void splitToNamespaces() {
    Collection ex = existing.values();
    for (Iterator it = ex.iterator(); it.hasNext(); ) {
	Object next = it.next();
	String uri = ((Resource)next).getID();
        Collection nsCol = namespaces.values();
	for (Iterator nsIt = nsCol.iterator(); nsIt.hasNext(); ){
	  Namespace ns = (Namespace)nsIt.next();
	  if ( uri.startsWith(ns.getURI())  ) {
	    ns.addName((Resource)next);
	    break;
	  }
	}
    }
  }

  public Model getModelPart(HashSet selectedNS) {
    splitToNamespaces();
    //create a new model
    Model mdl = new Model(false);
    mdl.setBaseURI(getBaseURI());
    //Determines the namespaces list of the new model
    HashMap namespaces = new HashMap();
    for (Iterator it = selectedNS.iterator(); it.hasNext(); ){
      Namespace ns = (Namespace)it.next();
      namespaces.put(ns.getURI(), ns);
    }
    mdl.setNamespaces(namespaces);
    //Contains the Namespace references of the selected namespaces
    for (Iterator it = selectedNS.iterator(); it.hasNext(); ){
      Namespace ns = (Namespace)it.next();
      HashSet names = ns.getNames();
      //Put each resource defined in the selected namespace in the new model
      for (Iterator it2 = names.iterator(); it2.hasNext(); ){
	Resource res = (Resource)it2.next();
	mdl.existing.put(res.getID(), res);
	//if its type/subclass/subproperty/domain/range list contains
	//classes/properties that they are not defined in one of the selected
	//ns include the class/property but only its type information i.e.,
	//init the arraylists of the object except for the type one.
	//The types of the classes contained in the type list are also included
	//Note ti ginetai gia isDefinedBy/seeAlso/value???
	if (res instanceof RDF_Class) {
	  RDF_Class rdf_class = (RDF_Class)res;
	  ArrayList list = rdf_class.getsubClassOf();
	  for (int i=0; i<list.size(); ) {
	    RDF_Class superClass = (RDF_Class)list.get(i++);
	    if ( !Namespace.isDefinedINNamespace(superClass, selectedNS) ) {
    	      list.remove(superClass);
	    }
	  }
	}//IF
	if (res instanceof RDF_Property) {
	  RDF_Property rdf_property = (RDF_Property)res;
	  ArrayList list = rdf_property.getsubPropertyOf();
	  for (int i=0; i<list.size(); ) {
	    RDF_Property superProperty = (RDF_Property)list.get(i++);
	    if ( !Namespace.isDefinedINNamespace(superProperty, selectedNS) ) {
	      list.remove(superProperty);
	    }
	  }
	  removeDR((RDF_Property)res, mdl, selectedNS);
	}//IF
	if ((res instanceof RDF_Class) || (res instanceof RDF_Property)) {
	  RDF_Resource rdf_resource = (RDF_Resource)res;
	  ArrayList list = rdf_resource.gettype();
	  for (int i=0; i<list.size(); ) {
	    RDF_Class rdf_class = (RDF_Class)list.get(i++);
	    if ( !Namespace.isDefinedINNamespace(rdf_class, selectedNS) ) {
	      list.remove(rdf_class);
      	    }
	  }
	}
      }
    }
    //Add in the new model all the data resources
    Collection dResources = getNodes();
    for (Iterator dIt = dResources.iterator(); dIt.hasNext(); ) {
      Resource resource = (Resource)dIt.next();
      if ( (!(resource instanceof RDF_Class)) && (!(resource instanceof RDF_Property))) {
	mdl.existing.put(resource.getID(), resource);
	if ( resource instanceof RDF_Resource ) {
	  RDF_Resource rdf_resource = (RDF_Resource)resource;
	  ArrayList list = rdf_resource.gettype();
	  for (int i=0; i<list.size(); ) {
	    RDF_Class rdf_class = (RDF_Class)list.get(i++);
	    if ( !Namespace.isDefinedINNamespace(rdf_class, selectedNS) ) {
	      list.remove(rdf_class);
	    }
	  }
	}
      }
    }
    return mdl;
  }

	/** Removes from the range and domain list of a property the classes
	 * and they are not defined in the selected namespaces
	 */
	private void removeDR(RDF_Property rdf_property, Model mdl, HashSet selectedNS) {
		ArrayList domains = rdf_property.getdomain();
		for (int i=0; i<domains.size(); ) {
			RDF_Class rdf_class = (RDF_Class)domains.get(i++);
			if ( !Namespace.isDefinedINNamespace(rdf_class, selectedNS) ) {
					domains.remove(rdf_class);
			}
		}
		ArrayList ranges = rdf_property.getrange();
		for (int i=0; i<ranges.size(); ) {
			RDF_Class rdf_class = (RDF_Class)ranges.get(i++);
			if ( !Namespace.isDefinedINNamespace(rdf_class, selectedNS) ) {
				ranges.remove(rdf_class);
			}
		}
	}

} // end of Class Model









