/* -*-Java-*- */

/* 
 * Copyright (C) 2006,2010  Anders Nilsson <anders.nilsson@control.lth.se>
 *
 * This file is part of OntologyCompiler.
 *
 * OntologyCompiler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * OntologyCompiler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 
 * You should have received a copy of the GNU General Public License
 * along with OntologyCompiler.  If not, see <http://www.gnu.org/licenses/>.
 */

aspect MiscUtilities {
    boolean Element.isTopLevel() {
		if ( getParent() != null ) {
			return getParent().getParent() instanceof RdfDeclaration;
		} else {
			return  false;
		}
    }

    syn lazy String Attribute.trim() {
		String s = getValue().getSTRING_LITERAL();
		s = s.replaceAll("-","_");
		if (s.indexOf('"') == 0) {
			s = s.substring(1,s.length()-1).trim();
		} 
		if (s.indexOf('#') > -1) {
			s = s.substring(s.indexOf('#')+1,s.length()).trim();
		} 
		if (s.indexOf(';') > -1) {
			s = s.substring(s.indexOf(';')+1,s.length()).trim();
		} 
		return s.trim();
    }

    eq RdfResource.trim() {
		String s = getValue().getSTRING_LITERAL();
		if (s.indexOf('"') == 0) {
			s = s.substring(1,s.length()-1).trim();
		} 
		if (s.indexOf('#') > -1) {
			s = s.substring(s.indexOf('#')+1,s.length()).trim();
		} 
		if (s.indexOf(';') > -1) {
			s = s.substring(s.indexOf(';')+1,s.length()).trim();
		} 
		if (s.equals("string")) {
			s = "String";
		}
		return s.trim();
    }

    boolean ComplexElement.hasRdfId() {
		for (int i=0; i<getNumAttribute(); i++) {
			if (getAttribute(i) instanceof RdfId) {
				return true;
			}
		}
		return false;

    }

    boolean ComplexElement.hasRdfAbout() {
		for (int i=0; i<getNumAttribute(); i++) {
			if (getAttribute(i) instanceof RdfAbout) {
				return true;
			}
		}
		return false;
    }

    boolean ComplexElement.hasRdfResource() {
		for (int i=0; i<getNumAttribute(); i++) {
			if (getAttribute(i) instanceof RdfResource) {
				return true;
			}
		}
		return false;
    }

    syn lazy String Element.getId() {
		return new String("Element has no ID");
    }

    eq ComplexElement.getId() {
		if (hasRdfId()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfId) {
					return getAttribute(i).trim();
				}
			}
		} else if (hasRdfAbout()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfAbout) {
					return getAttribute(i).trim();
				}
			}
		} else if (hasRdfResource()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfResource) {
					return getAttribute(i).trim();
				}
			}
		}
		// Fall through. Could not find Id, so let's return something
		// well known
		return "_Unknown_";
    }

	eq OwlValuesFrom.getId() {
		if (hasRdfAbout()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfAbout) {
					return getAttribute(i).trim();
				}
			}
		} else if (hasRdfResource()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfResource) {
					return getAttribute(i).trim();
				}
			}
		} else {
			for (int i=0; i<getNumElement(); i++) {
				ComplexElement e = (ComplexElement) getElement(i);
				if (e instanceof OClass) {
					return e.getId();
				}
			}
		}
		// Fall through. Could not find Id, so let's return something
		// well known
		return "_Unknown_";		
	}

	eq OwlProperty.getId() {
		if (hasRdfId()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfId) {
					return getAttribute(i).trim();
				}
			}
		} else if (hasRdfAbout()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfAbout) {
					return getAttribute(i).trim();
				}
			}
		} else if (hasRdfResource()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfResource) {
					return getAttribute(i).trim();
				}
			}
		} else {
			for (int i=0; i<getNumElement(); i++) {
				ComplexElement e = (ComplexElement) getElement(i);
				if (e instanceof OwlProperty) {
					return e.getId();
				}
			}
		}
		// Fall through. Could not find Id, so let's return something
		// well known
		return "_Unknown_";		
	}

	// eq RdfsDomain.getId() {
	// 	 System.out.println(((OwlClassUse) getElement(0)).getId());
	// return ((OwlClassUse)getElement(0)).getId();
	// }

    syn lazy String Element.type() = null;

    eq RdfsRange.type() {
		if (hasRdfResource()) {
			for (int i=0; i<getNumAttribute(); i++) {
				if (getAttribute(i) instanceof RdfResource) {
					return getAttribute(i).trim();
				}
			}
		}
		for (int i=0; i<getNumElement(); i++) {
			String s = getElement(i).type();
			if (s != null) {
				return s;
			}
		}
		// Fall through. Could not find Id, so let's return something
		// well known
		return "Thing";
    }

    eq OwlDataRange.type() {
		for (int i=0; i<getNumElement(); i++) {
			String s = getElement(i).type();
			if (s != null) {
				return s;
			}
		}	
		return null;
    }

    eq OwlOneOf.type() {
		for (int i=0; i<getNumElement(); i++) {
			String s = getElement(i).type();
			if (s != null) {
				return s;
			}
		}	
		return null;
    }

    eq RdfFirst.type() {
		for (int i=0; i<getNumAttribute(); i++) {
			if (getAttribute(i) instanceof RdfDatatype) {
				return getAttribute(i).trim();
			}
		}
		return null;
    }

    ComplexElement ComplexElement.getTopElement() {
		ASTNode e = this;
		while (e != null && !(e instanceof RdfDeclaration)) {
			e = e.getParent();
		}
		return (ComplexElement) e;
    }

	 syn boolean Declaration.isClassDecl() {
		  return getElement(0).isClass();
	 }
	eq OwlClassDecl.isClassDecl() = true;
	eq OwlClassUse.isClassDecl() = false;
	eq ClassDeclaration.isClassDecl() = false;
	eq IndividualDeclaration.isClassDecl() = false;
	syn boolean Declaration.isIndividualDecl() = getElement(0).isIndividual();
	eq IndividualDeclaration.isIndividualDecl() = false;
	eq ClassDeclaration.isIndividualDecl() = false;

	syn boolean Element.isClass() = false;
	eq Clazz.isClass() = true;

	syn boolean Element.isIndividual() = false;
	eq NamedIndividual.isIndividual() = true;

}

aspect RewriteClasses {

	// rewrite OClass {
	// 	when (isClassDecl())
	// 		to ClassDeclaration {
	// 		 System.out.println(getId());
	// 		ClassDeclaration c = new ClassDeclaration();
	// 		c.setElementList(getElementList());
	// 		c.setAttributeList(getAttributeList());
	// 		return c;
	// 	}
	// 	// when (isIndividualDecl())
	// 	// 	to IndividualDeclaration {
	// 	// 	IndividualDeclaration c = new IndividualDeclaration();
	// 	// 	c.setElementList(getElementList());
	// 	// 	return c;
	// 	// }
	// }

    rewrite OwlClass {
		when (isTopLevel())
			to OwlClassDecl {
			return new OwlClassDecl(new List(), getElementList(), getId());
		}
// 		when (hasRdfId())
// 			to OwlClassDecl {
// 			return new OwlClassDecl(new List(), getElementList(), getId());
// 		}
		when (!isTopLevel())
			to OwlClassUse {
			return new OwlClassUse(new List(), getElementList(), getId());
		}
    }

    rewrite RdfsSubClassOf {
		when (getNumAttribute()>0 && getAttribute(0) instanceof RdfResource)
			to RdfsSubClassOf {
			Value value = getAttribute(0).getValue();
			OwlClass oc = new OwlClass(new List().add(new RdfAbout(value)),
									   new List());
			return new RdfsSubClassOf(new List(), 
									  new List().add(oc));
		}
    }

    rewrite RdfsDomain {
		when (getNumAttribute()>0 && getAttribute(0) instanceof RdfResource)
			to RdfsDomain {
			Value value = getAttribute(0).getValue();
			OwlClass oc = new OwlClass(new List().add(new RdfAbout(value)),
									   new List());
			return new RdfsDomain(new List(), 
								  new List().add(oc));
		}
    }

	rewrite OwlClassDecl {
		when (getId().contains("-"))
			to OwlClassDecl {
			setId(getId().replaceAll("-","_"));
			return this;
		}
	}
}