/* * Copyright (c) 2013, University of Toronto. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package edu.toronto.cs.xml2rdf.mapping.generator; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.w3c.dom.Element; import edu.toronto.cs.xml2rdf.xml.XMLUtils; /** * @author Soheil Hassas Yeganeh <soheil@cs.toronto.edu> */ // TODO(soheil, eric): We need to update instances when merging two schemas. class AttributeInstance { public AttributeInstance(SchemaInstance instance, Element element) throws IOException { this(instance, XMLUtils.asString(element)); } AttributeInstance(SchemaInstance instance, String content) { this.content = content; this.schemaInstance = instance; } @Override public boolean equals(Object obj) { if (obj instanceof AttributeInstance) { AttributeInstance that = (AttributeInstance) obj; return content.equals(that.content) && schemaInstance.equals(that.schemaInstance); } return false; } @Override public int hashCode() { return content.hashCode() ^ schemaInstance.hashCode() << 7; } @Override public String toString() { return schemaInstance + "::" + content; } SchemaInstance schemaInstance; String content; } class Attribute { String name; String path; Schema parent; boolean key; Set<String> typeURIs = new HashSet<String>(); Map<SchemaInstance, Set<AttributeInstance>> instanceMap; Map<String, Set<AttributeInstance>> reverseInstanceMap; public Attribute(Schema parent, String name, String path, boolean key) { super(); this.name = name; this.path = path; this.parent = parent; this.key = key; instanceMap = new HashMap<SchemaInstance, Set<AttributeInstance>>(); reverseInstanceMap = new HashMap<String, Set<AttributeInstance>>(); } public void addInstance(AttributeInstance instance) { Set<AttributeInstance> attributes = instanceMap.get(instance.schemaInstance); if (attributes == null) { attributes = new HashSet<AttributeInstance>(); instanceMap.put(instance.schemaInstance, attributes); } attributes.add(instance); attributes = reverseInstanceMap.get(instance.content); if (attributes == null) { attributes = new HashSet<AttributeInstance>(); reverseInstanceMap.put(instance.content, attributes); } attributes.add(instance); } public boolean isOneToOne() { for (Map.Entry<SchemaInstance, Set<AttributeInstance>> entry : instanceMap.entrySet()) { if (entry.getValue().size() > 1) { return false; } } for (Map.Entry<String, Set<AttributeInstance>> entry : reverseInstanceMap.entrySet()) { if (entry.getValue().size() > 1) { return false; } } return true; } public void setParent(Schema parent) { this.parent = parent; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public boolean isKey() { return key; } public void setKey(boolean key) { this.key = key; } public Schema getParent() { return parent; } @Override public String toString() { return "A@ " + name; } @Override public boolean equals(Object obj) { if (obj instanceof Attribute) { Attribute attr = (Attribute) obj; return attr.name.equals(this.name) && attr.parent.equals(this.parent) && attr.path.equals(this.path); } return super.equals(obj); } @Override public int hashCode() { return name.hashCode(); } public Set<String> getTypeURIs() { return typeURIs; } public void setTypeURIs(Set<String> typeURIs) { this.typeURIs = typeURIs; } } class RelationInstance { public RelationInstance(SchemaInstance from, SchemaInstance to) { this.from = from; this.to = to; } SchemaInstance from; SchemaInstance to; @Override public int hashCode() { return from.hashCode() ^ to.hashCode() << 7; } @Override public boolean equals(Object obj) { if (obj instanceof RelationInstance) { RelationInstance that = (RelationInstance) obj; return from.equals(that.from) && to.equals(that.to); } return false; } @Override public String toString() { return "(" + from + "," + to + ")"; } } class Relation { String name; String path; Schema schema; Schema parent; Set<Attribute> lookupKeys; Map<SchemaInstance, Set<RelationInstance>> instanceMap; Map<SchemaInstance, Set<RelationInstance>> reverseInstanceMap; public Relation(Schema parent, String name, String path, Schema schema, Set<Attribute> lookupKeys) { super(); this.name = name; this.path = path; this.lookupKeys = lookupKeys; instanceMap = new HashMap<SchemaInstance, Set<RelationInstance>>(); reverseInstanceMap = new HashMap<SchemaInstance, Set<RelationInstance>>(); this.setParent(parent); this.setSchema(schema); } public void setParent(Schema parent) { // TODO(soheil): We might need to remove it here. this.parent = parent; parent.addRelation(this); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Schema getSchema() { return schema; } public void setSchema(Schema schema) { this.schema = schema; schema.addReverseRelation(this); } public Set<Attribute> getLookupKeys() { return lookupKeys; } @Override public String toString() { return "R@ " + name; } @Override public boolean equals(Object obj) { if (obj instanceof Relation) { Relation relation = (Relation) obj; return relation.name.equals(this.name) && relation.schema.equals(this.schema); } return false; } @Override public int hashCode() { return name.hashCode(); } public void addInstance(RelationInstance instance) { Set<RelationInstance> relations = instanceMap.get(instance.from); if (relations == null) { relations = new HashSet<RelationInstance>(); instanceMap.put(instance.from, relations); } relations.add(instance); relations = reverseInstanceMap.get(instance.to); if (relations == null) { relations = new HashSet<RelationInstance>(); reverseInstanceMap.put(instance.to, relations); } relations.add(instance); } public boolean isOneToOne() { for (Map.Entry<SchemaInstance, Set<RelationInstance>> entry : instanceMap.entrySet()) { if (entry.getValue().size() > 1) { return false; } } for (Map.Entry<SchemaInstance, Set<RelationInstance>> entry : reverseInstanceMap.entrySet()) { if (entry.getValue().size() > 1) { return false; } } return true; } } class SchemaInstance { public SchemaInstance(Element element) throws IOException { this(XMLUtils.asString(element)); } SchemaInstance(String content) { this.content = content; } @Override public boolean equals(Object obj) { if (obj instanceof SchemaInstance) { SchemaInstance that = (SchemaInstance) obj; return content.equals(that.content); } return false; } @Override public int hashCode() { return content.hashCode(); } @Override public String toString() { return content; } String content; } class Schema { Set<String> typeURIs = new HashSet<String>(); Element element; String id; String name; Set<Attribute> attributes; Set<Relation> relations; Set<Relation> reverseRelations; String path; Schema parent; Set<SchemaInstance> instances; Schema(Schema parent, Element element, String path) { attributes = new HashSet<Attribute>(); relations = new HashSet<Relation>(); reverseRelations = new HashSet<Relation>(); instances = new HashSet<SchemaInstance>(); this.path = path; this.element = element; this.parent = parent; this.name = element.getNodeName(); } Schema(Schema parent, String name, String path) { attributes = new HashSet<Attribute>(); relations = new HashSet<Relation>(); reverseRelations = new HashSet<Relation>(); this.path = path; this.parent = parent; this.name = name; } void addAttribute(Attribute attribute) { attributes.add(attribute); } void addReverseRelation(Relation relation) { reverseRelations.add(relation); } void addRelation(Relation relation) { relations.add(relation); } public Set<Relation> getRelations() { return relations; } public void setRelations(Set<Relation> relations) { this.relations = relations; } public String getName() { return name; } public void setName(String name) { this.name = name; } // public Element getElement() { // return element; // } // // void setElement(Element element) { // this.element = element; // } public String getId() { return id; } public void setId(String id) { this.id = id; } public Set<Attribute> getAttributes() { return attributes; } public void setAttributes(Set<Attribute> attributes) { this.attributes = attributes; } public String getPath() { return path; } @Override public String toString() { return "S@ " + name; } @Override public int hashCode() { return name.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof Schema) { Schema schema = (Schema) obj; return name.equals(schema.name); } return false; } public Set<String> getTypeURIs() { return typeURIs; } public void setTypeURIs(Set<String> typeURIs) { this.typeURIs = typeURIs; } } class OntologyLink extends Schema { OntologyLink(Schema parent, Element element, String path, Set<String> typeURIs) { super(parent, element, path); this.typeURIs = typeURIs; } }