/******************************************************************************* * Copyright (c) 2009, 2010 Fraunhofer IWU and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.komma.model.validation; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.Set; import net.enilink.commons.iterator.IExtendedIterator; import net.enilink.komma.common.util.BasicDiagnostic; import net.enilink.komma.common.util.Diagnostic; import net.enilink.komma.common.util.DiagnosticChain; import net.enilink.komma.core.IReference; import net.enilink.komma.em.concepts.IClass; import net.enilink.komma.em.concepts.IProperty; import net.enilink.komma.em.concepts.IResource; import net.enilink.komma.model.IObject; import net.enilink.komma.model.ModelPlugin; import net.enilink.komma.model.ModelUtil; /** * A validity checker for basic {@link IObject} constraints. */ public class Diagnostician implements IValidator.SubstitutionLabelProvider, IValidator { protected IValidator.Registry validatorRegistry; public Diagnostician(IValidator.Registry validatorRegistry) { this.validatorRegistry = validatorRegistry; } public String getObjectLabel(IResource object) { return ModelUtil.getLabel(object); } public String getPropertyLabel(IProperty property) { return ModelUtil.getLabel(property); } public String getValueLabel(Object value) { return ModelUtil.getLabel(value); } public Map<Object, Object> createDefaultContext() { Map<Object, Object> context = new HashMap<Object, Object>(); context.put(IValidator.SubstitutionLabelProvider.class, this); context.put(IValidator.class, this); return context; } public BasicDiagnostic createDefaultDiagnostic(IResource object) { return new BasicDiagnostic(DefaultValidator.DIAGNOSTIC_SOURCE, 0, ModelPlugin.getDefault().getString("DiagnosticRoot_diagnostic", new Object[] { getObjectLabel(object) }), new Object[] { object }); } public BasicDiagnostic createDefaultDiagnostic(IReference datatype, Object value) { return new BasicDiagnostic(DefaultValidator.DIAGNOSTIC_SOURCE, 0, ModelPlugin.getDefault().getString("DiagnosticRoot_diagnostic", new Object[] { getValueLabel(value) }), new Object[] { value, datatype }); } public Diagnostic validate(IObject object) { BasicDiagnostic diagnostics = createDefaultDiagnostic(object); validate(object, diagnostics, createDefaultContext()); return diagnostics; } public Diagnostic validate(IResource object, Map<?, ?> contextEntries) { BasicDiagnostic diagnostics = createDefaultDiagnostic(object); Map<Object, Object> context = createDefaultContext(); context.putAll(contextEntries); validate(object, diagnostics, context); return diagnostics; } public boolean validate(IResource object, DiagnosticChain diagnostics, Map<Object, Object> context) { return validate(object.getDirectNamedClasses().toList(), object, diagnostics, context); } public boolean validate(Collection<? extends IClass> classes, IResource object, DiagnosticChain diagnostics, Map<Object, Object> context) { Set<IClass> seenClasses = new HashSet<IClass>(); Queue<IClass> classesQueue = new LinkedList<IClass>(classes); while (!classes.isEmpty()) { IClass clazz = classesQueue.remove(); seenClasses.add(clazz); Object validator = validatorRegistry.get(clazz.getURI() .trimFragment()); if (validator == null) { IExtendedIterator<IClass> superClasses = clazz .getDirectNamedSuperClasses(); if (classes.isEmpty() && !superClasses.hasNext()) { validator = validatorRegistry.get(null); break; } else { for (IClass superClass : superClasses) { if (!seenClasses.contains(superClass)) { classesQueue.add(superClass); } } } } boolean result = ((IValidator) validator).validate( Arrays.asList(clazz), object, diagnostics, context); if (result || diagnostics != null) { result &= doValidateContents(object, diagnostics, context); } return result; } return true; } protected boolean doValidateContents(IResource object, DiagnosticChain diagnostics, Map<Object, Object> context) { Collection<IResource> contents = object.getContents(); if (!contents.isEmpty()) { Iterator<IResource> i = contents.iterator(); IResource child = i.next(); boolean result = validate(child, diagnostics, context); while (i.hasNext() && (result || diagnostics != null)) { child = i.next(); result &= validate(child, diagnostics, context); } return result; } else { return true; } } public Diagnostic validate(IReference datatype, Object value) { BasicDiagnostic diagnostics = createDefaultDiagnostic(datatype, value); validate(datatype, value, diagnostics, createDefaultContext()); return diagnostics; } public boolean validate(IReference datatype, Object value, DiagnosticChain diagnostics, Map<Object, Object> context) { Object validator = validatorRegistry.get(datatype.getURI() .trimFragment()); if (validator == null) { validator = validatorRegistry.get(null); } return ((IValidator) validator).validate(datatype, value, diagnostics, context); } }