001package eu.cqse.check.framework.core; 002 003import org.conqat.lib.commons.assertion.CCSMAssert; 004import org.conqat.lib.commons.reflect.ReflectionUtils; 005 006import eu.cqse.check.framework.core.option.CheckOptionWrapper; 007 008/** 009 * A instance of a custom check. Multiple {@link CheckInstance}s of one 010 * {@link CheckImplementationBase} subtype can exist in order to be executed in 011 * parallel by multiple worker threads (each {@link CheckInstance} is backed by 012 * a separate instance of the {@link CheckImplementationBase} subtype). 013 */ 014public class CheckInstance { 015 016 /** The check's implementation. */ 017 private final CheckImplementationBase checkImplementation; 018 019 /** The check info. */ 020 private final CheckInfo checkInfo; 021 022 /** 023 * Creates a new check instance with the given check info. This given check info 024 * must not be null. 025 */ 026 public CheckInstance(CheckInfo checkInfo) throws CheckException { 027 CCSMAssert.isNotNull(checkInfo); 028 this.checkInfo = checkInfo; 029 checkImplementation = checkInfo.instantiateCheckImplementation(); 030 } 031 032 /** Initializes the check. */ 033 public void initialize() throws CheckException { 034 checkImplementation.initialize(); 035 } 036 037 /** Executes this check with the given context. */ 038 public void execute() throws CheckException { 039 checkImplementation.execute(); 040 } 041 042 /** @see #checkImplementation */ 043 public CheckImplementationBase getCheckImplementation() { 044 return checkImplementation; 045 } 046 047 /** @see #checkInfo */ 048 public CheckInfo getCheckInfo() { 049 return checkInfo; 050 } 051 052 /** 053 * Initializes the underlying check implementation (calls 054 * {@link CheckImplementationBase#initialize()}) and then sets the check context 055 * of the underlying check implementation to the given one. 056 */ 057 public void initializeAndSetContext(ICheckContext context) throws CheckException { 058 CCSMAssert.isNotNull(context); 059 checkImplementation.setContext(null); // ensure that initialize does not use old context info 060 initialize(); 061 /* 062 * initialize(); must be called while no context is set. This ensures that 063 * implementations of the CheckImplementationBase#initialize method can't access 064 * check-phase results (e.g., via context#accessPhaseResult). Initialization is 065 * done only once for a batch of analyzed files but we store dependencies on 066 * check-phase results on single-file granularity. Therefore, accessing 067 * check-phase results from initialize() would mess up the information stored in 068 * CheckPhaseResultDependencyIndex. 069 */ 070 checkImplementation.setContext(context); 071 } 072 073 /** Sets the option with the given name to the given value. */ 074 public <T> void setOption(String name, T value) { 075 CheckOptionWrapper<?> option = checkInfo.getOptions().get(name); 076 if (option != null) { 077 CCSMAssert.isTrue(ReflectionUtils.isAssignable(value.getClass(), option.getType()), 078 "The given value must have the same type as the option to set."); 079 @SuppressWarnings("unchecked") 080 CheckOptionWrapper<T> castedOption = (CheckOptionWrapper<T>) option; 081 castedOption.setOption(checkImplementation, value); 082 } 083 } 084}