class SchemaValidator implements SchemaValidatorIF {

  @Override
  public void validate(TopicIF topic) throws SchemaViolationException {
    // find appropriate class
    TopicClass klass = (TopicClass) findClass(topic, schema.getTopicClasses());
    if (klass == null) {
      if (schema.isStrict())
        handler.violation("No matching rule for topic",
                          topic.getTopicMap(), topic, null);
      return;
    }

    // pick out constraint collections
    Collection basenamecs = klass.getAllTopicNameConstraints();
    Collection occurrencecs = klass.getAllOccurrenceConstraints();
    Collection rolecs = klass.getAllRoleConstraints();
    
    // other classes
    Collection others = klass.getOtherClasses();
    Iterator it = topic.getTypes().iterator();
    while (it.hasNext()) {
      TopicIF tclass = (TopicIF) it.next();
      if (klass.getTypeSpecification().matchType(tclass))
        continue;

      boolean found = false;
      Iterator it2 = others.iterator();
      while (it2.hasNext()) {
        TypeSpecification typespec = (TypeSpecification) it2.next();

        if (typespec.matchType(tclass)) {
          found = true;
          TopicClass otherclass =
            (TopicClass) findClassFor(tclass, schema.getTopicClasses());

          if (otherclass != null) {
            basenamecs.addAll(otherclass.getAllTopicNameConstraints());
            occurrencecs.addAll(otherclass.getAllOccurrenceConstraints());
            rolecs.addAll(otherclass.getAllRoleConstraints());
          }
          break;
        }
      }

      if (!found)
        handler.violation("Topic instance of illegal other class",
                          topic, tclass, null);
    }

    // characteristics
    validate(topic, basenamecs, topic.getTopicNames(), klass.isStrict());
    validate(topic, occurrencecs, topic.getOccurrences(), klass.isStrict());
    validate(topic, rolecs, topic.getRoles(), klass.isStrict());
  }

    SchemaValidator(OSLSchema schema);

}