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    }