001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.plugins.core.timemachine;
021    
022    import org.sonar.api.batch.*;
023    import org.sonar.api.database.DatabaseSession;
024    import org.sonar.api.database.model.RuleFailureModel;
025    import org.sonar.api.database.model.Snapshot;
026    import org.sonar.api.resources.Project;
027    import org.sonar.api.resources.Resource;
028    import org.sonar.api.rules.Rule;
029    import org.sonar.api.rules.RuleFinder;
030    import org.sonar.api.rules.Violation;
031    import org.sonar.api.violations.ViolationQuery;
032    import org.sonar.batch.index.ResourcePersister;
033    import org.sonar.core.NotDryRun;
034    
035    import java.util.List;
036    
037    @NotDryRun
038    @DependedUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
039    public class ViolationPersisterDecorator implements Decorator {
040    
041      private ViolationTrackingDecorator tracker;
042      private ResourcePersister persister;
043      private RuleFinder ruleFinder;
044      private DatabaseSession session;
045    
046      public ViolationPersisterDecorator(ViolationTrackingDecorator tracker, ResourcePersister persister, RuleFinder ruleFinder, DatabaseSession session) {
047        this.tracker = tracker;
048        this.persister = persister;
049        this.ruleFinder = ruleFinder;
050        this.session = session;
051      }
052    
053      public boolean shouldExecuteOnProject(Project project) {
054        return true;
055      }
056    
057      @DependsUpon
058      public Class dependsOnTracker() {
059        return ViolationTrackingDecorator.class;
060      }
061    
062      public void decorate(Resource resource, DecoratorContext context) {
063        saveViolations(context.getProject(), context.getViolations(ViolationQuery.create().forResource(resource).setSwitchMode(ViolationQuery.SwitchMode.BOTH)));
064      }
065    
066      void saveViolations(Project project, List<Violation> violations) {
067        for (Violation violation : violations) {
068          RuleFailureModel referenceViolation = tracker.getReferenceViolation(violation);
069          save(project, violation, referenceViolation);
070        }
071        session.commit();
072      }
073    
074      public void save(Project project, Violation violation, RuleFailureModel referenceViolation) {
075        Snapshot snapshot = persister.saveResource(project, violation.getResource());
076    
077        RuleFailureModel model = createModel(violation);
078        if (referenceViolation != null) {
079          model.setPermanentId(referenceViolation.getPermanentId());
080        }
081        model.setSnapshotId(snapshot.getId());
082        session.saveWithoutFlush(model);
083    
084        if (model.getPermanentId() == null) {
085          model.setPermanentId(model.getId());
086          session.saveWithoutFlush(model);
087        }
088        violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim)
089      }
090    
091    
092      private RuleFailureModel createModel(Violation violation) {
093        RuleFailureModel model = new RuleFailureModel();
094        Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());
095        model.setRuleId(rule.getId());
096        model.setPriority(violation.getSeverity());
097        model.setLine(violation.getLineId());
098        model.setMessage(violation.getMessage());
099        model.setCost(violation.getCost());
100        model.setChecksum(violation.getChecksum());
101        model.setCreatedAt(violation.getCreatedAt());
102        model.setSwitchedOff(violation.isSwitchedOff());
103        return model;
104      }
105    }