001 package com.hammurapi.review.util; 002 003 import java.util.logging.Level; 004 import java.util.logging.Logger; 005 006 import com.hammurapi.config.Named; 007 import com.hammurapi.config.NamedObjectDefinition; 008 import com.hammurapi.config.ObjectDefinition; 009 import com.hammurapi.config.bootstrap.ConfigurationException; 010 import com.hammurapi.config.bootstrap.TokenExpander; 011 import com.hammurapi.config.bootstrap.TokenExpander.TokenSource; 012 import com.hammurapi.config.runtime.Component; 013 import com.hammurapi.config.runtime.ConfigurationContext; 014 import com.hammurapi.convert.ConvertingService; 015 import com.hammurapi.reasoning.impl.InferenceMethodNode; 016 import com.hammurapi.review.Inspector; 017 import com.hammurapi.review.InspectorSet; 018 import com.hammurapi.review.LanguageElement; 019 import com.hammurapi.review.Observation; 020 import com.hammurapi.review.ReviewFactory; 021 import com.hammurapi.review.Violation; 022 import com.hammurapi.review.Warning; 023 024 public class InspectorMethodNode extends InferenceMethodNode<Object> implements Component<ObjectDefinition> { 025 private static final Logger logger = Logger.getLogger(InspectorMethodNode.class.getName()); 026 027 /** 028 * Injects inspector and source into observation. 029 */ 030 @Override 031 protected void onConclusion(Object[] args, Object conclusion) { 032 if (inspector!=null && conclusion instanceof Observation) { 033 final Observation observation = (Observation) conclusion; 034 observation.setReportedBy(inspector); 035 if (observation.getSource()==null) { 036 for (Object arg: args) { 037 LanguageElement src = ConvertingService.convert(arg, LanguageElement.class); 038 if (src!=null) { 039 observation.setSource(src); 040 break; 041 } 042 } 043 } 044 045 if (observation instanceof Violation && ((Violation) observation).getMessage()==null && inspector!=null) { 046 if (inspector.getMessageTemplate()==null) { 047 ((Violation) observation).setMessage(inspector.getName()+": "+inspector.getDescription()); 048 } else { 049 TokenSource ts = new TokenSource() { 050 051 @Override 052 public String getToken(String name) { 053 Violation violation = (Violation) observation; 054 Object ret = violation.getProperty(name); 055 if (ret!=null) { 056 return String.valueOf(ret); 057 } 058 for (Named property: inspector.getProperty()) { 059 if (name.equals(property.getName()) && property instanceof NamedObjectDefinition) { 060 return ((NamedObjectDefinition) property).getValue(); 061 } 062 } 063 064 return "*** WARNING: Unresolved token "+name+" ***"; 065 } 066 067 }; 068 069 TokenExpander te = new TokenExpander(ts); 070 try { 071 ((Violation) observation).setMessage(te.expand(inspector.getMessageTemplate())); 072 } catch (ConfigurationException e) { 073 ((Violation) observation).setMessage("Failed to expand inspector message template '"+inspector.getMessageTemplate()+"': "+e); 074 logger.log(Level.SEVERE, "Failed to expand inspector message template '"+inspector.getMessageTemplate()+"': "+e, e); 075 } 076 } 077 } 078 } 079 } 080 081 /** 082 * Creates warnings for exceptions in inspector methods. 083 */ 084 @Override 085 protected boolean handleException(Object[] args, Exception e) throws Exception { 086 Warning warning = ReviewFactory.eINSTANCE.createWarning(); 087 warning.setMessage("Exception during inference: "+e); 088 warning.setCause(e); 089 onConclusion(args, warning); 090 knowledgeBase.put(warning); 091 return true; 092 } 093 094 private Inspector inspector; 095 096 @Override 097 public void init(ConfigurationContext<ObjectDefinition> context) throws ConfigurationException { 098 if (inspectorName!=null) { 099 findInspector(context.lookup(InspectorSet.class)); 100 } 101 } 102 103 private boolean findInspector(InspectorSet inspectorSet) { 104 for (Inspector i: inspectorSet.getInspectors()) { 105 if (inspectorName.equals(i.getName())) { 106 inspector = i; 107 return true; 108 } 109 } 110 111 for (InspectorSet base: inspectorSet.getBase()) { 112 if (findInspector(base)) { 113 return true; 114 } 115 } 116 117 return false; 118 } 119 120 private String inspectorName; 121 122 public void setInspectorName(String inspectorName) { 123 this.inspectorName = inspectorName; 124 } 125 }