aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2010-09-21 21:25:29 +0000
committersimonbrandhof <simon.brandhof@gmail.com>2010-09-21 21:25:29 +0000
commitd46e081eacea3680bae90faa5df1ae43157d1e87 (patch)
tree3e7bea37e9b306f335cd6a52910b6ffb4068bec2 /sonar-server
parentd4963b41c34bc8a0d94ad80fe098cd088bb4a5a0 (diff)
downloadsonarqube-d46e081eacea3680bae90faa5df1ae43157d1e87.tar.gz
sonarqube-d46e081eacea3680bae90faa5df1ae43157d1e87.zip
quality models: limit the methods of org.sonar.api.qualitymodel.ModelFinder to read methods. Management methods are restricted to core => extracted to org.sonar.server.qualitymodel.ModelManager
Diffstat (limited to 'sonar-server')
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualitymodel/DefaultModelManager.java124
-rw-r--r--sonar-server/src/main/java/org/sonar/server/qualitymodel/ModelManager.java33
-rw-r--r--sonar-server/src/main/java/org/sonar/server/startup/RegisterQualityModels.java12
-rw-r--r--sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java3
-rw-r--r--sonar-server/src/test/java/org/sonar/server/qualitymodel/DefaultModelManagerTest.java121
-rw-r--r--sonar-server/src/test/java/org/sonar/server/startup/RegisterQualityModelsTest.java8
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/noDefinitionsToRegister-result.xml10
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerModelProperties-result.xml16
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerOnlyNewDefinitions-result.xml13
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/reset-result.xml15
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/shared.xml12
12 files changed, 357 insertions, 12 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 5bbb113f777..bd154a4f770 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -49,6 +49,7 @@ import org.sonar.server.database.JndiDatabaseConnector;
import org.sonar.server.filters.FilterExecutor;
import org.sonar.server.mavendeployer.MavenRepository;
import org.sonar.server.plugins.*;
+import org.sonar.server.qualitymodel.DefaultModelManager;
import org.sonar.server.rules.*;
import org.sonar.server.startup.*;
import org.sonar.server.ui.AuthenticatorFactory;
@@ -155,6 +156,7 @@ public final class Platform {
pluginRepository.registerPlugins(servicesContainer);
servicesContainer.as(Characteristics.CACHE).addComponent(DefaultModelFinder.class); // depends on plugins
+ servicesContainer.as(Characteristics.CACHE).addComponent(DefaultModelManager.class);
servicesContainer.as(Characteristics.CACHE).addComponent(Plugins.class);
servicesContainer.as(Characteristics.CACHE).addComponent(ChartFactory.class);
servicesContainer.as(Characteristics.CACHE).addComponent(Languages.class);
diff --git a/sonar-server/src/main/java/org/sonar/server/qualitymodel/DefaultModelManager.java b/sonar-server/src/main/java/org/sonar/server/qualitymodel/DefaultModelManager.java
new file mode 100644
index 00000000000..84ccb3999bb
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/qualitymodel/DefaultModelManager.java
@@ -0,0 +1,124 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.server.qualitymodel;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.qualitymodel.ModelDefinition;
+import org.sonar.api.utils.Logs;
+import org.sonar.api.utils.SonarException;
+import org.sonar.jpa.session.DatabaseSessionFactory;
+
+import javax.persistence.Query;
+
+public final class DefaultModelManager implements ServerComponent, ModelManager {
+
+ private ModelDefinition[] definitions;
+ private DatabaseSessionFactory sessionFactory;
+
+ public DefaultModelManager(DatabaseSessionFactory sessionFactory, ModelDefinition[] definitions) {
+ this.sessionFactory = sessionFactory;
+ this.definitions = definitions;
+ }
+
+ /**
+ * This constructor is used when there are no templates
+ */
+ public DefaultModelManager(DatabaseSessionFactory sessionFactory) {
+ this.sessionFactory = sessionFactory;
+ this.definitions = new ModelDefinition[0];
+ }
+
+ /**
+ * Executed when the server starts
+ */
+ public ModelManager registerDefinitions() {
+ DatabaseSession session = sessionFactory.getSession();
+ for (ModelDefinition definition : definitions) {
+ if (StringUtils.isNotBlank(definition.getName()) && !exists(session, definition.getName())) {
+ Logs.INFO.info("Register quality model: " + definition.getName());
+ Model model = definition.create();
+ if (StringUtils.isBlank(model.getName())) {
+ model.setName(definition.getName());
+ }
+ insert(session, model);
+ session.commit();
+ }
+ }
+ return this;
+ }
+
+ public Model reset(String name) {
+ ModelDefinition definition = findDefinitionByName(name);
+ if (definition == null) {
+ throw new SonarException("Can not reset quality model. Definition not found: " + name);
+ }
+
+ LoggerFactory.getLogger(getClass()).info("Reset quality model: " + name);
+ Model model = definition.create();
+ return reset(model);
+ }
+
+
+ Model reset(Model model) {
+ DatabaseSession session = sessionFactory.getSession();
+ try {
+ delete(session, model.getName());
+ model = insert(session, model);
+ session.commit();
+ return model;
+
+ } catch (RuntimeException e) {
+ session.rollback();
+ throw e;
+ }
+ }
+
+ public ModelDefinition findDefinitionByName(String name) {
+ for (ModelDefinition definition : definitions) {
+ if (StringUtils.equals(name, definition.getName())) {
+ return definition;
+ }
+ }
+ return null;
+ }
+
+ public static void delete(DatabaseSession session, String name) {
+ Model model = session.getSingleResult(Model.class, "name", name);
+ if (model != null) {
+ session.removeWithoutFlush(model);
+ session.commit();
+ }
+ }
+
+ public static Model insert(DatabaseSession session, Model model) {
+ return (Model) session.saveWithoutFlush(model);
+ }
+
+ public static boolean exists(DatabaseSession session, String name) {
+ Query query = session.getEntityManager().createQuery("SELECT COUNT(qm) FROM " + Model.class.getSimpleName() + " qm WHERE qm.name=:name");
+ query.setParameter("name", name);
+ Number count = (Number) query.getSingleResult();
+ return count.intValue() > 0;
+ }
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/qualitymodel/ModelManager.java b/sonar-server/src/main/java/org/sonar/server/qualitymodel/ModelManager.java
new file mode 100644
index 00000000000..8bd0f005e9e
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/qualitymodel/ModelManager.java
@@ -0,0 +1,33 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+
+package org.sonar.server.qualitymodel;
+
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.qualitymodel.ModelDefinition;
+
+public interface ModelManager {
+
+ ModelManager registerDefinitions();
+
+ Model reset(String name);
+
+ ModelDefinition findDefinitionByName(String name);
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RegisterQualityModels.java b/sonar-server/src/main/java/org/sonar/server/startup/RegisterQualityModels.java
index b364bcbadff..424bd7378bc 100644
--- a/sonar-server/src/main/java/org/sonar/server/startup/RegisterQualityModels.java
+++ b/sonar-server/src/main/java/org/sonar/server/startup/RegisterQualityModels.java
@@ -20,25 +20,23 @@
package org.sonar.server.startup;
import org.sonar.api.utils.TimeProfiler;
-import org.sonar.core.qualitymodel.DefaultModelFinder;
+import org.sonar.server.qualitymodel.ModelManager;
public final class RegisterQualityModels {
- private DefaultModelFinder provider;
+ private ModelManager manager;
/**
- *
- * @param provider
* @param registerRulesBeforeModels used only to be started after the creation of check templates
*/
// NOSONAR the parameter registerRulesBeforeModels is only used to provide the execution order by picocontainer
- public RegisterQualityModels(DefaultModelFinder provider, RegisterRules registerRulesBeforeModels) {
- this.provider = provider;
+ public RegisterQualityModels(ModelManager manager, RegisterRules registerRulesBeforeModels) {
+ this.manager = manager;
}
public void start() {
TimeProfiler profiler = new TimeProfiler().start("Register quality models");
- provider.registerDefinitions();
+ manager.registerDefinitions();
profiler.stop();
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
index 880fec3b984..73180166d1a 100644
--- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
+++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
@@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.Plugin;
import org.sonar.api.Plugins;
import org.sonar.api.Property;
+import org.sonar.api.ServerComponent;
import org.sonar.api.profiles.ProfileExporter;
import org.sonar.api.profiles.ProfileImporter;
import org.sonar.api.resources.Language;
@@ -52,7 +53,7 @@ import org.sonar.updatecenter.common.Version;
import java.util.Collection;
import java.util.List;
-public class JRubyFacade {
+public final class JRubyFacade implements ServerComponent {
public FilterResult executeFilter(Filter filter) {
return getContainer().getComponent(FilterExecutor.class).execute(filter);
diff --git a/sonar-server/src/test/java/org/sonar/server/qualitymodel/DefaultModelManagerTest.java b/sonar-server/src/test/java/org/sonar/server/qualitymodel/DefaultModelManagerTest.java
new file mode 100644
index 00000000000..058e649d5bc
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/qualitymodel/DefaultModelManagerTest.java
@@ -0,0 +1,121 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.server.qualitymodel;
+
+import org.junit.Test;
+import org.sonar.api.qualitymodel.Characteristic;
+import org.sonar.api.qualitymodel.Model;
+import org.sonar.api.qualitymodel.ModelDefinition;
+import org.sonar.jpa.test.AbstractDbUnitTestCase;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+
+public class DefaultModelManagerTest extends AbstractDbUnitTestCase {
+
+ @Test
+ public void reset() {
+ setupData("shared");
+ DefaultModelManager manager = new DefaultModelManager(getSessionFactory());
+
+ Model model = Model.createByName("M1");
+ Characteristic c1 = model.createCharacteristicByName("NEWM1C1");
+ Characteristic c1a = model.createCharacteristicByName("NEWM1C1A");
+ c1.addChild(c1a);
+
+ model.createCharacteristicByName("NEWM1C2");
+ manager.reset(model);
+
+ model = getSession().getSingleResult(Model.class, "name", "M1");
+ assertNotNull(model);
+ assertThat(model.getCharacteristics().size(), is(3));
+ assertThat(model.getCharacteristicByName("NEWM1C1A").getParents().size(), is(1));
+ assertNotNull(model.getCharacteristicByName("NEWM1C1A").getParent("NEWM1C1"));
+ }
+
+ @Test
+ public void noDefinitionsToRegister() {
+ setupData("shared");
+ ModelManager provider = new DefaultModelManager(getSessionFactory());
+ provider.registerDefinitions();
+
+ // same state
+ List<Model> models = getSession().getResults(Model.class);
+ assertThat(models.size(), is(2));
+ }
+
+ @Test
+ public void registerOnlyNewDefinitions() {
+ setupData("shared");
+
+ ModelDefinition existingDefinition = new FakeDefinition("M1", Model.create());
+ ModelDefinition newDefinition = new FakeDefinition("NEWMODEL", Model.create());
+
+ ModelDefinition[] definitions = new ModelDefinition[]{existingDefinition, newDefinition};
+ ModelManager manager = new DefaultModelManager(getSessionFactory(), definitions);
+ manager.registerDefinitions();
+
+ List<Model> models = getSession().getResults(Model.class);
+ assertThat(models.size(), is(3)); // 2 existing + one new
+ }
+
+ @Test
+ public void registerModelProperties() {
+ Model model = Model.create();
+ Characteristic characteristic = model.createCharacteristicByName("Usability");
+ characteristic.setProperty("factor", 2.0);
+ characteristic.setProperty("severity", "BLOCKER");
+
+ setupData("shared");
+ ModelDefinition def = new FakeDefinition("with-properties", model);
+ ModelManager manager = new DefaultModelManager(getSessionFactory(), new ModelDefinition[]{def});
+ manager.registerDefinitions();
+ checkTables("registerModelProperties", "quality_models", "characteristics", "characteristic_properties");
+ }
+
+ @Test
+ public void exists() {
+ setupData("shared");
+ assertTrue(DefaultModelManager.exists(getSession(), "M1"));
+ }
+
+ @Test
+ public void notExists() {
+ setupData("shared");
+ assertFalse(DefaultModelManager.exists(getSession(), "UNKNOWN"));
+ }
+}
+
+class FakeDefinition extends ModelDefinition {
+ private final Model model;
+
+ public FakeDefinition(String name, Model model) {
+ super(name);
+ this.model = model;
+ }
+
+ @Override
+ public Model create() {
+ return model;
+ }
+
+} \ No newline at end of file
diff --git a/sonar-server/src/test/java/org/sonar/server/startup/RegisterQualityModelsTest.java b/sonar-server/src/test/java/org/sonar/server/startup/RegisterQualityModelsTest.java
index fda03fc2077..002b2abff9a 100644
--- a/sonar-server/src/test/java/org/sonar/server/startup/RegisterQualityModelsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/startup/RegisterQualityModelsTest.java
@@ -20,7 +20,7 @@
package org.sonar.server.startup;
import org.junit.Test;
-import org.sonar.core.qualitymodel.DefaultModelFinder;
+import org.sonar.server.qualitymodel.ModelManager;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -29,9 +29,9 @@ public class RegisterQualityModelsTest {
@Test
public void isASimpleBridgeOverProvider() {
- DefaultModelFinder provider = mock(DefaultModelFinder.class);
- RegisterQualityModels startup = new RegisterQualityModels(provider, null);
+ ModelManager manager = mock(ModelManager.class);
+ RegisterQualityModels startup = new RegisterQualityModels(manager, null);
startup.start();
- verify(provider).registerDefinitions();
+ verify(manager).registerDefinitions();
}
}
diff --git a/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/noDefinitionsToRegister-result.xml b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/noDefinitionsToRegister-result.xml
new file mode 100644
index 00000000000..c26de5371bb
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/noDefinitionsToRegister-result.xml
@@ -0,0 +1,10 @@
+<dataset>
+ <quality_models id="1" name="M1" />
+ <quality_models id="2" name="M2" />
+
+ <characteristics id="1" kee="M1C1" name="M1C1" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+ <characteristics id="2" kee="M1C2" name="M1C2" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="2" description="[null]" enabled="true" />
+ <characteristics id="3" kee="M2C1" name="M2C1" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true"/>
+
+ <characteristic_edges child_id="2" parent_id="1"/>
+</dataset> \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerModelProperties-result.xml b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerModelProperties-result.xml
new file mode 100644
index 00000000000..6deb78039ac
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerModelProperties-result.xml
@@ -0,0 +1,16 @@
+<dataset>
+ <quality_models id="1" name="M1" />
+ <quality_models id="2" name="M2" />
+ <quality_models id="3" name="with-properties" />
+
+ <characteristics id="1" kee="M1C1" name="M1C1" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+ <characteristics id="2" kee="M1C2" name="M1C2" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="2" description="[null]" enabled="true" />
+ <characteristics id="3" kee="M2C1" name="M2C1" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true"/>
+ <characteristics id="4" kee="USABILITY" name="Usability" quality_model_id="3" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true"/>
+
+ <characteristic_edges child_id="2" parent_id="1"/>
+
+ <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+ <characteristic_properties id="2" characteristic_id="4" kee="factor" value="2.0" text_value="[null]" />
+ <characteristic_properties id="3" characteristic_id="4" kee="severity" value="[null]" text_value="BLOCKER" />
+</dataset> \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerOnlyNewDefinitions-result.xml b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerOnlyNewDefinitions-result.xml
new file mode 100644
index 00000000000..455cfb41cde
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/registerOnlyNewDefinitions-result.xml
@@ -0,0 +1,13 @@
+<dataset>
+ <quality_models id="1" name="M1" />
+ <quality_models id="2" name="M2" />
+
+ <!-- NEW MODEL -->
+ <quality_models id="3" name="NEWMODEL" />
+
+ <characteristics id="1" kee="M1C1" name="M1C1" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+ <characteristics id="2" kee="M1C2" name="M1C2" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="2" description="[null]" enabled="true" />
+ <characteristics id="3" kee="M2C1" name="M2C1" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true"/>
+
+ <characteristic_edges child_id="2" parent_id="1"/>
+</dataset> \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/reset-result.xml b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/reset-result.xml
new file mode 100644
index 00000000000..bbffd8e4a77
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/reset-result.xml
@@ -0,0 +1,15 @@
+<dataset>
+ <!--<quality_models id="1" name="M1" />-->
+ <quality_models id="2" name="M2" />
+ <quality_models id="3" name="M1" />
+
+ <!--<characteristics id="1" kee="M1C1" name="M1C1" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />-->
+ <!--<characteristics id="2" kee="M1C2" name="M1C2" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="2" description="[null]" enabled="true"/>-->
+ <characteristics id="3" kee="M2C1" name="M2C1" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+ <characteristics id="4" kee="NEWM1C1A" name="NEWM1C1A" quality_model_id="3" rule_id="[null]" characteristic_order="1" depth="2" description="[null]" enabled="true"/>
+ <characteristics id="5" kee="NEWM1C1" name="NEWM1C1" quality_model_id="3" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true"/>
+ <characteristics id="6" kee="NEWM1C2" name="NEWM1C2" quality_model_id="3" rule_id="[null]" characteristic_order="2" depth="1" description="[null]" enabled="true"/>
+
+ <!--<characteristic_edges child_id="2" parent_id="1"/>-->
+ <characteristic_edges child_id="4" parent_id="5"/>
+</dataset> \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/shared.xml b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/shared.xml
new file mode 100644
index 00000000000..c509eb3f937
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/qualitymodel/DefaultModelManagerTest/shared.xml
@@ -0,0 +1,12 @@
+<dataset>
+ <quality_models id="1" name="M1" />
+ <quality_models id="2" name="M2" />
+
+ <characteristics id="1" kee="M1C1" name="M1C1" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true" />
+ <characteristics id="2" kee="M1C2" name="M1C2" quality_model_id="1" rule_id="[null]" characteristic_order="1" depth="2" description="[null]" enabled="true" />
+ <characteristics id="3" kee="M2C1" name="M2C1" quality_model_id="2" rule_id="[null]" characteristic_order="1" depth="1" description="[null]" enabled="true"/>
+
+ <characteristic_edges child_id="2" parent_id="1"/>
+
+ <characteristic_properties id="1" characteristic_id="1" kee="foo" value="[null]" text_value="bar" />
+</dataset> \ No newline at end of file