/* * The contents of this file are subject to the Open Software License * Version 3.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.opensource.org/licenses/osl-3.0.txt * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. */ package org.mulgara.krule; import java.util.Collections; import java.util.Set; import org.apache.log4j.Logger; import org.mulgara.query.Answer; import org.mulgara.query.QueryException; import org.mulgara.query.TuplesException; import org.mulgara.query.Variable; import org.mulgara.resolver.OperationContext; import org.mulgara.resolver.spi.Resolver; import org.mulgara.resolver.spi.ResolverException; import org.mulgara.resolver.spi.SystemResolver; /** * A rule that generates no data, but instead checks that the data is consistent. * * @created Mar 18, 2009 * @author Paula Gearon * @copyright © 2008 <a href="http://www.topazproject.org/">The Topaz Project</a> * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a> */ public class ConsistencyCheck extends Rule { /** Serialization ID */ private static final long serialVersionUID = 5514372363770138432L; /** Logger. */ private static final Logger logger = Logger.getLogger(ConsistencyCheck.class.getName()); /** * Creates the consistency test as a rule. * @param name The name of this rule. */ public ConsistencyCheck(String name) { super(name); } /** * Adds a target for triggering. These are not legal for consistency checks. * @param target The rule to be triggered when this rule is executed. */ public void addTriggerTarget(Rule target) { throw new IllegalStateException("Consistency checks cannot trigger other rules."); } /** * Retrieves the list of subordinate rules. * @return an immutable set of the subordinate rules. */ public Set<Rule> getTriggerTargets() { return Collections.emptySet(); } /** * Sets the query for this rule. * @param queryStruct The query which retrieves data for this rule. */ public void setQueryStruct(QueryStruct queryStruct) throws KruleStructureException { this.query = queryStruct.extractQuery(); } /** * Runs this test. * TODO: count the size of each individual constraint * * @param context The context to query against. * @param resolver The resolver to add data with. * @param sysResolver The resolver to localize data with. */ public void execute(OperationContext context, Resolver resolver, SystemResolver sysResolver) throws QueryException, TuplesException, ResolverException { // Tests the output of this rule Answer answer = null; logger.debug("Running consistency check: " + name); try { answer = context.doQuery(query); } catch (Exception e) { throw new QueryException("Unable to access data in rule.", e); } try { // compare the size of the result data long c = answer.getRowCount(); if (0 != c) { if (logger.isDebugEnabled()) { logger.debug("Failed consistency check: " + name); logOutput(answer); } throw new QueryException("Consistency check failed for rule \"" + name + "\". Got " + c + " failure results."); } } finally { answer.close(); } } /** * Send the result of a query to the logger. * @param ans The result of the query to log. */ private void logOutput(Answer ans) { try { ans.beforeFirst(); Variable[] vars = ans.getVariables(); StringBuilder line = new StringBuilder(); for (Variable v: vars) line.append(v).append(" "); logger.debug(line.toString()); line = new StringBuilder(); while (ans.next()) { for (int c = 0; c < vars.length; c++) { if (c != 0) line.append(", "); line.append(ans.getObject(c)); } line.append("\n"); } logger.debug(line); } catch (TuplesException e) { logger.error("Error reading failure in consistency check.", e); } } }