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 }