001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 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    @DependsUpon({ DecoratorBarriers.END_OF_VIOLATION_TRACKING, DecoratorBarriers.START_VIOLATION_PERSISTENCE })
039    @DependedUpon(DecoratorBarriers.END_OF_VIOLATION_PERSISTENCE)
040    public class ViolationPersisterDecorator implements Decorator {
041    
042      private ViolationTrackingDecorator tracker;
043      private ResourcePersister persister;
044      private RuleFinder ruleFinder;
045      private DatabaseSession session;
046    
047      public ViolationPersisterDecorator(ViolationTrackingDecorator tracker, ResourcePersister persister, RuleFinder ruleFinder, DatabaseSession session) {
048        this.tracker = tracker;
049        this.persister = persister;
050        this.ruleFinder = ruleFinder;
051        this.session = session;
052      }
053    
054      public boolean shouldExecuteOnProject(Project project) {
055        return true;
056      }
057    
058      public void decorate(Resource resource, DecoratorContext context) {
059        saveViolations(context.getProject(), context.getViolations(ViolationQuery.create().forResource(resource).setSwitchMode(ViolationQuery.SwitchMode.BOTH)));
060      }
061    
062      void saveViolations(Project project, List<Violation> violations) {
063        for (Violation violation : violations) {
064          RuleFailureModel referenceViolation = tracker.getReferenceViolation(violation);
065          save(project, violation, referenceViolation);
066        }
067        session.commit();
068      }
069    
070      public void save(Project project, Violation violation, RuleFailureModel referenceViolation) {
071        Snapshot snapshot = persister.saveResource(project, violation.getResource());
072    
073        RuleFailureModel model = createModel(violation);
074        if (referenceViolation != null) {
075          model.setPermanentId(referenceViolation.getPermanentId());
076        }
077        model.setSnapshotId(snapshot.getId());
078        session.saveWithoutFlush(model);
079    
080        if (model.getPermanentId() == null) {
081          model.setPermanentId(model.getId());
082          session.saveWithoutFlush(model);
083        }
084        violation.setMessage(model.getMessage());// the message can be changed in the class RuleFailure (truncate + trim)
085      }
086    
087    
088      private RuleFailureModel createModel(Violation violation) {
089        RuleFailureModel model = new RuleFailureModel();
090        Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey());
091        model.setRuleId(rule.getId());
092        model.setPriority(violation.getSeverity());
093        model.setLine(violation.getLineId());
094        model.setMessage(violation.getMessage());
095        model.setCost(violation.getCost());
096        model.setChecksum(violation.getChecksum());
097        model.setCreatedAt(violation.getCreatedAt());
098        model.setSwitchedOff(violation.isSwitchedOff());
099        model.setPersonId(violation.getPersonId());
100        return model;
101      }
102    }