001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube 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     * SonarQube 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 License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.batch.phases;
021    
022    import com.tinkerpop.blueprints.Graph;
023    import org.apache.commons.io.IOUtils;
024    import org.sonar.api.component.Perspective;
025    import org.sonar.batch.index.ScanPersister;
026    import org.sonar.core.component.ComponentVertex;
027    import org.sonar.core.component.GraphPerspectiveBuilder;
028    import org.sonar.core.component.PerspectiveBuilder;
029    import org.sonar.core.component.ScanGraph;
030    import org.sonar.core.graph.SubGraph;
031    import org.sonar.core.graph.graphson.GraphsonMode;
032    import org.sonar.core.graph.graphson.GraphsonWriter;
033    import org.sonar.core.graph.jdbc.GraphDto;
034    import org.sonar.core.graph.jdbc.GraphDtoMapper;
035    import org.sonar.core.persistence.DbSession;
036    import org.sonar.core.persistence.MyBatis;
037    
038    import java.io.StringWriter;
039    
040    public class GraphPersister implements ScanPersister {
041      private final MyBatis myBatis;
042      private final ScanGraph projectGraph;
043      private final GraphPerspectiveBuilder[] builders;
044    
045      public GraphPersister(MyBatis myBatis, ScanGraph projectGraph, GraphPerspectiveBuilder[] builders) {
046        this.myBatis = myBatis;
047        this.projectGraph = projectGraph;
048        this.builders = builders;
049      }
050    
051      public void persist() {
052        DbSession session = myBatis.openSession(true);
053        GraphDtoMapper mapper = session.getMapper(GraphDtoMapper.class);
054        try {
055          for (ComponentVertex component : projectGraph.getComponents()) {
056            persistComponentGraph(mapper, component);
057          }
058          session.commit();
059        } finally {
060          session.close();
061        }
062      }
063    
064      private void persistComponentGraph(GraphDtoMapper mapper, ComponentVertex component) {
065        Long snapshotId = (Long) component.element().getProperty("sid");
066        if (snapshotId != null) {
067          for (PerspectiveBuilder builder : builders) {
068            GraphPerspectiveBuilder graphPerspectiveBuilder = (GraphPerspectiveBuilder) builder;
069            Perspective perspective = graphPerspectiveBuilder.getPerspectiveLoader().load(component);
070            if (perspective != null) {
071              serializePerspectiveData(mapper, component, snapshotId, graphPerspectiveBuilder);
072            }
073          }
074        }
075      }
076    
077      private void serializePerspectiveData(GraphDtoMapper mapper, ComponentVertex component, Long snapshotId,
078                                            GraphPerspectiveBuilder builder) {
079        Graph subGraph = SubGraph.extract(component.element(), builder.path());
080        String data = write(subGraph);
081        mapper.insert(new GraphDto()
082          .setData(data)
083          .setFormat("graphson")
084          .setPerspective(builder.getPerspectiveLoader().getPerspectiveKey())
085          .setVersion(1)
086          .setResourceId((Long) component.element().getProperty("rid"))
087          .setSnapshotId(snapshotId)
088          .setRootVertexId(component.element().getId().toString())
089        );
090      }
091    
092      private String write(Graph graph) {
093        StringWriter output = new StringWriter();
094        try {
095          new GraphsonWriter().write(graph, output, GraphsonMode.EXTENDED);
096          return output.toString();
097        } finally {
098          IOUtils.closeQuietly(output);
099        }
100      }
101    }