public void define(Context context) {
NewController controller = context
.createController(API_ENDPOINT)
- .setDescription("Logs search and views");
+ .setDescription("Tracking of activities");
search.define(controller);
controller.done();
import org.sonar.api.resources.Languages;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.activity.Activity;
+import org.sonar.server.activity.index.ActivityDoc;
import org.sonar.server.activity.index.ActivityNormalizer;
import org.sonar.server.search.ws.BaseMapping;
+import org.sonar.server.search.ws.SearchOptions;
import org.sonar.server.text.MacroInterpreter;
import java.util.Map;
/**
- * Conversion between Log and WS JSON response
+ * Conversion between {@link org.sonar.server.activity.index.ActivityDoc} and WS JSON response
*/
-public class ActivityMapping extends BaseMapping {
-
+public class ActivityMapping extends BaseMapping<ActivityDoc, Object> {
public ActivityMapping(Languages languages, MacroInterpreter macroInterpreter) {
- super();
- addIndexStringField("type", ActivityNormalizer.LogFields.TYPE.field());
- addIndexStringField("action", ActivityNormalizer.LogFields.ACTION.field());
- addIndexDatetimeField("createdAt", ActivityNormalizer.LogFields.CREATED_AT.field());
- addIndexStringField("login", ActivityNormalizer.LogFields.LOGIN.field());
- addIndexStringField("message", ActivityNormalizer.LogFields.MESSAGE.field());
- addField("details", new DetailField());
+ map("type", ActivityNormalizer.LogFields.TYPE.field());
+ map("action", ActivityNormalizer.LogFields.ACTION.field());
+ mapDateTime("createdAt", ActivityNormalizer.LogFields.CREATED_AT.field());
+ map("login", ActivityNormalizer.LogFields.LOGIN.field());
+ map("message", ActivityNormalizer.LogFields.MESSAGE.field());
+ map("details", new IndexMapper<ActivityDoc, Object>(ActivityNormalizer.LogFields.DETAILS.field()) {
+ @Override
+ public void write(JsonWriter json, ActivityDoc activity, Object context) {
+ json.name("details").beginObject();
+ for (Map.Entry<String, String> detail : activity.details().entrySet()) {
+ json.prop(detail.getKey(), detail.getValue());
+ }
+ json.endObject();
+ }
+ });
}
- private static class DetailField extends IndexField<Activity> {
- DetailField() {
- super(ActivityNormalizer.LogFields.DETAILS.field());
- }
-
- @Override
- public void write(JsonWriter json, Activity activity) {
- json.name("details").beginObject();
- for (Map.Entry<String, String> detail : activity.details().entrySet()) {
- json.prop(detail.getKey(), detail.getValue());
- }
- json.endObject();
- }
+ public void write(Activity activity, JsonWriter writer, SearchOptions options) {
+ doWrite((ActivityDoc)activity, null, writer, options);
}
+
}
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.activity.Activity;
import org.sonar.server.activity.ActivityService;
-import org.sonar.server.activity.index.ActivityDoc;
import org.sonar.server.activity.index.ActivityQuery;
import org.sonar.server.search.QueryOptions;
import org.sonar.server.search.Result;
void define(WebService.NewController controller) {
WebService.NewAction action = controller
.createAction(SEARCH_ACTION)
- .setDescription("Search for a logs")
+ .setDescription("Search for activities")
.setSince("4.4")
.setInternal(true)
.setHandler(this);
// Other parameters
action.createParam(PARAM_TYPE)
- .setDescription("Select types of log to search")
+ .setDescription("Types of activities to search")
.setPossibleValues(Activity.Type.values())
.setDefaultValue(StringUtils.join(Activity.Type.values(), ","));
private void writeLogs(Result<Activity> result, JsonWriter json, SearchOptions options) {
json.name("logs").beginArray();
for (Activity log : result.getHits()) {
- mapping.write((ActivityDoc) log, json, options);
+ mapping.write(log, json, options);
}
json.endArray();
}
import org.sonar.server.rule.ReactivationException;
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleService;
-import org.sonar.server.search.BaseDoc;
import java.io.OutputStreamWriter;
private void writeResponse(Response response, RuleKey ruleKey) {
Rule rule = service.getNonNullByKey(ruleKey);
JsonWriter json = response.newJsonWriter().beginObject().name("rule");
- mapping.write((BaseDoc) rule, json);
+ mapping.write(rule, json, null /* TODO replace by SearchOptions immutable constant */);
json.endObject().close();
}
stream.setStatus(409);
stream.setMediaType(MimeTypes.JSON);
JsonWriter json = JsonWriter.of(new OutputStreamWriter(stream.output())).beginObject().name("rule");
- mapping.write((BaseDoc) rule, json);
+ mapping.write(rule, json, null /* TODO replace by SearchOptions immutable constant */);
json.endObject().close();
}
}
*/
package org.sonar.server.rule.ws;
+import com.google.common.collect.Maps;
import org.apache.commons.lang.StringEscapeUtils;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
+import org.sonar.api.server.debt.DebtCharacteristic;
+import org.sonar.api.server.debt.DebtModel;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.markdown.Markdown;
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleParam;
+import org.sonar.server.rule.index.RuleDoc;
import org.sonar.server.rule.index.RuleNormalizer;
import org.sonar.server.search.ws.BaseMapping;
+import org.sonar.server.search.ws.SearchOptions;
import org.sonar.server.text.MacroInterpreter;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.Map;
+
/**
- * Conversion between RuleDoc and WS JSON response
+ * Conversion of {@link org.sonar.server.rule.index.RuleDoc} to WS JSON document
*/
-public class RuleMapping extends BaseMapping {
-
- public RuleMapping(Languages languages, MacroInterpreter macroInterpreter) {
- super();
- addIndexStringField("repo", RuleNormalizer.RuleField.REPOSITORY.field());
- addIndexStringField("name", RuleNormalizer.RuleField.NAME.field());
- addIndexDatetimeField("createdAt", RuleNormalizer.RuleField.CREATED_AT.field());
- addField("htmlDesc", new HtmlDescField(macroInterpreter));
- addIndexStringField("severity", RuleNormalizer.RuleField.SEVERITY.field());
- addIndexStringField("status", RuleNormalizer.RuleField.STATUS.field());
- addIndexStringField("internalKey", RuleNormalizer.RuleField.INTERNAL_KEY.field());
- addIndexBooleanField("isTemplate", RuleNormalizer.RuleField.IS_TEMPLATE.field());
- addIndexStringField("templateKey", RuleNormalizer.RuleField.TEMPLATE_KEY.field());
- addIndexArrayField("tags", RuleNormalizer.RuleField.TAGS.field());
- addIndexArrayField("sysTags", RuleNormalizer.RuleField.SYSTEM_TAGS.field());
- addField("defaultDebtChar", new IndexStringField("defaultDebtChar", RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field()));
- addField("defaultDebtChar", new IndexStringField("defaultDebtSubChar", RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field()));
- addField("debtChar", new IndexStringField("debtChar", RuleNormalizer.RuleField.CHARACTERISTIC.field(),
+public class RuleMapping extends BaseMapping<RuleDoc, RuleMappingContext> {
+
+ private final DebtModel debtModel;
+
+ public RuleMapping(final Languages languages, final MacroInterpreter macroInterpreter, final DebtModel debtModel) {
+ this.debtModel = debtModel;
+
+ mapBasicFields(languages);
+ mapDescriptionFields(macroInterpreter);
+ mapDebtFields();
+ mapParamFields();
+ }
+
+ private void mapBasicFields(final Languages languages) {
+ map("repo", RuleNormalizer.RuleField.REPOSITORY.field());
+ map("name", RuleNormalizer.RuleField.NAME.field());
+ mapDateTime("createdAt", RuleNormalizer.RuleField.CREATED_AT.field());
+ map("severity", RuleNormalizer.RuleField.SEVERITY.field());
+ map("status", RuleNormalizer.RuleField.STATUS.field());
+ map("internalKey", RuleNormalizer.RuleField.INTERNAL_KEY.field());
+ mapBoolean("isTemplate", RuleNormalizer.RuleField.IS_TEMPLATE.field());
+ map("templateKey", RuleNormalizer.RuleField.TEMPLATE_KEY.field());
+ mapArray("tags", RuleNormalizer.RuleField.TAGS.field());
+ mapArray("sysTags", RuleNormalizer.RuleField.SYSTEM_TAGS.field());
+ map("lang", RuleNormalizer.RuleField.LANGUAGE.field());
+ map("langName", new IndexMapper<RuleDoc, RuleMappingContext>(RuleNormalizer.RuleField.LANGUAGE.field()) {
+ @Override
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ Language lang = languages.get(rule.language());
+ json.prop("langName", lang != null ? lang.getName() : null);
+ }
+ });
+ }
+
+ private void mapDescriptionFields(final MacroInterpreter macroInterpreter) {
+ map("htmlDesc", new Mapper<RuleDoc, RuleMappingContext>() {
+ @Override
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ String html = rule.htmlDescription();
+ if (html != null) {
+ if (rule.isManual() || rule.templateKey() != null) {
+ String desc = StringEscapeUtils.escapeHtml(html);
+ desc = desc.replaceAll("\\n", "<br/>");
+ json.prop("htmlDesc", desc);
+ } else {
+ json.prop("htmlDesc", macroInterpreter.interpret(html));
+ }
+ }
+ }
+ });
+ map("noteLogin", RuleNormalizer.RuleField.NOTE_LOGIN.field());
+ map("mdNote", RuleNormalizer.RuleField.NOTE.field());
+ map("htmlNote", new IndexMapper<RuleDoc, RuleMappingContext>(RuleNormalizer.RuleField.NOTE.field()) {
+ @Override
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ String markdownNote = rule.markdownNote();
+ if (markdownNote != null) {
+ json.prop("htmlNote", macroInterpreter.interpret(Markdown.convertToHtml(markdownNote)));
+ }
+ }
+ });
+ }
+
+ private void mapDebtFields() {
+ map("defaultDebtChar", new IndexStringMapper("defaultDebtChar", RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field()));
+ map("defaultDebtSubChar", new IndexStringMapper("defaultDebtSubChar", RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field()));
+ map("debtChar", new IndexStringMapper("debtChar", RuleNormalizer.RuleField.CHARACTERISTIC.field(),
RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field()));
- addField("debtChar", new IndexStringField("debtSubChar", RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(),
+ map("debtSubChar", new IndexStringMapper("debtSubChar", RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(),
RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field()));
- addField("debtRemFn", new IndexStringField("debtRemFnType", RuleNormalizer.RuleField.DEBT_FUNCTION_TYPE.field(),
+ map("debtCharName", new CharacteristicNameMapper());
+ map("debtSubCharName", new SubCharacteristicNameMapper());
+ map("debtRemFn", new IndexStringMapper("debtRemFnType", RuleNormalizer.RuleField.DEBT_FUNCTION_TYPE.field(),
RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_TYPE.field()));
- addField("debtRemFn", new IndexStringField("debtRemFnCoeff", RuleNormalizer.RuleField.DEBT_FUNCTION_COEFFICIENT.field(),
+ map("debtRemFn", new IndexStringMapper("debtRemFnCoeff", RuleNormalizer.RuleField.DEBT_FUNCTION_COEFFICIENT.field(),
RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_COEFFICIENT.field()));
- addField("debtRemFn", new IndexStringField("debtRemFnOffset", RuleNormalizer.RuleField.DEBT_FUNCTION_OFFSET.field(),
+ map("debtRemFn", new IndexStringMapper("debtRemFnOffset", RuleNormalizer.RuleField.DEBT_FUNCTION_OFFSET.field(),
RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_OFFSET.field()));
- addField("defaultDebtRemFn", new IndexStringField("defaultDebtRemFnType", RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_TYPE.field()));
- addField("defaultDebtRemFn", new IndexStringField("defaultDebtRemFnCoeff", RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_COEFFICIENT.field()));
- addField("defaultDebtRemFn", new IndexStringField("defaultDebtRemFnOffset", RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_OFFSET.field()));
- addIndexStringField("effortToFixDescription", RuleNormalizer.RuleField.FIX_DESCRIPTION.field());
- addIndexStringField("mdNote", RuleNormalizer.RuleField.NOTE.field());
- addField("htmlNote", new HtmlNoteField(macroInterpreter));
- addIndexStringField("noteLogin", RuleNormalizer.RuleField.NOTE_LOGIN.field());
- addIndexStringField("lang", RuleNormalizer.RuleField.LANGUAGE.field());
- addField("langName", new LangNameField(languages));
- addField("debtCharName", new CharacteristicNameField());
- addField("debtSubCharName", new SubCharacteristicNameField());
- addField("debtOverloaded", new OverriddenField());
- addField("params", new ParamsField());
+ map("defaultDebtRemFn", new IndexStringMapper("defaultDebtRemFnType", RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_TYPE.field()));
+ map("defaultDebtRemFn", new IndexStringMapper("defaultDebtRemFnCoeff", RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_COEFFICIENT.field()));
+ map("defaultDebtRemFn", new IndexStringMapper("defaultDebtRemFnOffset", RuleNormalizer.RuleField.DEFAULT_DEBT_FUNCTION_OFFSET.field()));
+ map("effortToFixDescription", RuleNormalizer.RuleField.FIX_DESCRIPTION.field());
+ map("debtOverloaded", new OverriddenMapper());
}
- private static class ParamsField extends IndexField<Rule> {
- ParamsField() {
- super(RuleNormalizer.RuleField.PARAMS.field());
- }
-
- @Override
- public void write(JsonWriter json, Rule rule) {
- json.name("params").beginArray();
- for (RuleParam param : rule.params()) {
- json
- .beginObject()
- .prop("key", param.key())
- .prop("desc", param.description())
- .prop("defaultValue", param.defaultValue())
- .endObject();
+ private void mapParamFields() {
+ map("params", new IndexMapper<RuleDoc, RuleMappingContext>(RuleNormalizer.RuleField.PARAMS.field()) {
+ @Override
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ json.name("params").beginArray();
+ for (RuleParam param : rule.params()) {
+ json
+ .beginObject()
+ .prop("key", param.key())
+ .prop("desc", param.description())
+ .prop("defaultValue", param.defaultValue())
+ .endObject();
+ }
+ json.endArray();
}
- json.endArray();
- }
+ });
}
- private static class LangNameField extends IndexField<Rule> {
- private final Languages languages;
-
- private LangNameField(Languages languages) {
- super(RuleNormalizer.RuleField.LANGUAGE.field());
- this.languages = languages;
+ public void write(Rule rule, JsonWriter json, @Nullable SearchOptions options) {
+ RuleMappingContext context = new RuleMappingContext();
+ if (needDebtCharacteristicNames(options) && rule.debtCharacteristicKey() != null) {
+ // load debt characteristics if requested
+ context.add(debtModel.characteristicByKey(rule.debtCharacteristicKey()));
}
+ if (needDebtSubCharacteristicNames(options) && rule.debtSubCharacteristicKey() != null) {
+ context.add(debtModel.characteristicByKey(rule.debtSubCharacteristicKey()));
+ }
+ doWrite((RuleDoc) rule, context, json, options);
+ }
- @Override
- public void write(JsonWriter json, Rule rule) {
- String langKey = rule.language();
- Language lang = languages.get(langKey);
- json.prop("langName", lang != null ? lang.getName() : null);
+ public void write(Collection<Rule> rules, JsonWriter json, @Nullable SearchOptions options) {
+ if (!rules.isEmpty()) {
+ RuleMappingContext context = new RuleMappingContext();
+ if (needDebtCharacteristicNames(options) || needDebtSubCharacteristicNames(options)) {
+ // load all debt characteristics
+ context.addAll(debtModel.allCharacteristics());
+ }
+ for (Rule rule : rules) {
+ doWrite((RuleDoc) rule, context, json, options);
+ }
}
}
- private static class HtmlNoteField extends IndexField<Rule> {
- private final MacroInterpreter macroInterpreter;
+ private boolean needDebtCharacteristicNames(@Nullable SearchOptions options) {
+ return options == null || options.hasField("debtCharName");
+ }
+
+ private boolean needDebtSubCharacteristicNames(@Nullable SearchOptions options) {
+ return options == null || options.hasField("debtSubCharName");
+ }
- private HtmlNoteField(MacroInterpreter macroInterpreter) {
- super(RuleNormalizer.RuleField.NOTE.field());
- this.macroInterpreter = macroInterpreter;
+ private static class CharacteristicNameMapper extends IndexMapper<RuleDoc, RuleMappingContext> {
+ private CharacteristicNameMapper() {
+ super(RuleNormalizer.RuleField.CHARACTERISTIC.field(), RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field());
}
@Override
- public void write(JsonWriter json, Rule rule) {
- String markdownNote = rule.markdownNote();
- if (markdownNote != null) {
- json.prop("htmlNote", macroInterpreter.interpret(Markdown.convertToHtml(markdownNote)));
- }
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ json.prop("debtCharName", context.debtCharacteristicName(rule.debtCharacteristicKey()));
}
}
- private static class HtmlDescField implements Field<Rule> {
- private final MacroInterpreter macroInterpreter;
-
- private HtmlDescField(MacroInterpreter macroInterpreter) {
- this.macroInterpreter = macroInterpreter;
+ private static class SubCharacteristicNameMapper extends IndexMapper<RuleDoc, RuleMappingContext> {
+ private SubCharacteristicNameMapper() {
+ super(RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(), RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field());
}
@Override
- public void write(JsonWriter json, Rule rule) {
- String html = rule.htmlDescription();
- if (html != null) {
- if (rule.isManual() || rule.templateKey() != null) {
- String desc = StringEscapeUtils.escapeHtml(html);
- desc = desc.replaceAll("\\n", "<br/>");
- json.prop("htmlDesc", desc);
- } else {
- json.prop("htmlDesc", macroInterpreter.interpret(html));
- }
- }
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ json.prop("debtSubCharName", context.debtCharacteristicName(rule.debtSubCharacteristicKey()));
}
}
- private static class CharacteristicNameField implements Field<Rule> {
+ private static class OverriddenMapper implements Mapper<RuleDoc, RuleMappingContext> {
@Override
- public void write(JsonWriter json, Rule rule) {
- // TODO set characteristic name
- json.prop("debtCharName", rule.debtCharacteristicKey());
+ public void write(JsonWriter json, RuleDoc rule, RuleMappingContext context) {
+ json.prop("debtOverloaded", rule.debtOverloaded());
}
}
+}
- private static class SubCharacteristicNameField implements Field<Rule> {
- @Override
- public void write(JsonWriter json, Rule rule) {
- // TODO set characteristic name
- json.prop("debtSubCharName", rule.debtSubCharacteristicKey());
+class RuleMappingContext {
+ private final Map<String, String> debtCharacteristicNamesByKey = Maps.newHashMap();
+
+ @CheckForNull
+ public String debtCharacteristicName(String key) {
+ return debtCharacteristicNamesByKey.get(key);
+ }
+
+ void add(@Nullable DebtCharacteristic c) {
+ if (c != null) {
+ debtCharacteristicNamesByKey.put(c.key(), c.name());
}
}
- private static class OverriddenField implements Field<Rule> {
- @Override
- public void write(JsonWriter json, Rule rule) {
- json.prop("debtOverloaded", rule.debtOverloaded());
+ void addAll(Collection<DebtCharacteristic> coll) {
+ for (DebtCharacteristic c : coll) {
+ add(c);
}
}
}
action
.createParam(PARAM_KEY)
- .setDescription("Single or list of keys of rule to search for")
+ .setDescription("Key of rule to search for")
.setExampleValue("squid:S001");
action
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleService;
-import org.sonar.server.search.BaseDoc;
/**
* @since 4.4
throw new NotFoundException("Rule not found: " + key);
}
JsonWriter json = response.newJsonWriter().beginObject().name("rule");
- mapping.write((BaseDoc) rule, json);
+ mapping.write(rule, json, null /* TODO replace by SearchOptions immutable constant */);
if (request.mandatoryParamAsBoolean(PARAM_ACTIVES)) {
activeRuleCompleter.completeShow(rule, json);
import org.sonar.server.rule.Rule;
import org.sonar.server.rule.RuleService;
import org.sonar.server.rule.RuleUpdate;
-import org.sonar.server.search.BaseDoc;
public class UpdateAction implements RequestHandler {
return update;
}
- private RuleUpdate createRuleUpdate(RuleKey key){
+ private RuleUpdate createRuleUpdate(RuleKey key) {
Rule rule = service.getByKey(key);
if (rule == null) {
throw new NotFoundException("This rule does not exists : " + key);
private void writeResponse(Response response, RuleKey ruleKey) {
Rule rule = service.getNonNullByKey(ruleKey);
JsonWriter json = response.newJsonWriter().beginObject().name("rule");
- mapping.write((BaseDoc) rule, json);
+ mapping.write(rule, json, null /* TODO replace by SearchOptions immutable constant */);
json.endObject().close();
}
}
import java.util.Set;
/**
- * Mapping of search documents (see BaseDoc) to WS JSON responses
+ * Mapping of search documents (see {@link org.sonar.server.search.BaseDoc}) to WS JSON responses
*/
-public abstract class BaseMapping implements ServerComponent {
+public abstract class BaseMapping<DOC extends BaseDoc, CTX> implements ServerComponent {
- private final Multimap<String, String> indexFields = LinkedHashMultimap.create();
- private final Multimap<String, BaseMapping.Field> fields = LinkedHashMultimap.create();
+ private final Multimap<String, String> indexFieldsByWsFields = LinkedHashMultimap.create();
+ private final Multimap<String, Mapper> mappers = LinkedHashMultimap.create();
+ /**
+ * All the WS supported fields
+ */
public Set<String> supportedFields() {
- return fields.keySet();
+ return mappers.keySet();
}
public QueryOptions newQueryOptions(SearchOptions options) {
List<String> optionFields = options.fields();
if (optionFields != null) {
for (String optionField : optionFields) {
- result.addFieldsToReturn(this.indexFields.get(optionField));
+ result.addFieldsToReturn(indexFieldsByWsFields.get(optionField));
}
}
return result;
}
- public void write(BaseDoc doc, JsonWriter json) {
- write(doc, json, null);
+ /**
+ * Write all document fields
+ */
+ protected void doWrite(DOC doc, @Nullable CTX context, JsonWriter json) {
+ doWrite(doc, context, json, null);
}
- public void write(BaseDoc doc, JsonWriter json, @Nullable SearchOptions options) {
+ /**
+ * Write only requested document fields
+ */
+ protected void doWrite(DOC doc, @Nullable CTX context, JsonWriter json, @Nullable SearchOptions options) {
json.beginObject();
json.prop("key", doc.keyField());
if (options == null || options.fields() == null) {
// return all fields
- for (BaseMapping.Field field : fields.values()) {
- field.write(json, doc);
+ for (Mapper mapper : mappers.values()) {
+ mapper.write(json, doc, context);
}
} else {
for (String optionField : options.fields()) {
- for (BaseMapping.Field field : fields.get(optionField)) {
- field.write(json, doc);
+ for (Mapper mapper : mappers.get(optionField)) {
+ mapper.write(json, doc, context);
}
}
}
json.endObject();
}
- protected BaseMapping addIndexStringField(String key, String indexKey) {
- return addField(key, new IndexStringField(key, indexKey));
+ protected BaseMapping map(String key, String indexKey) {
+ return map(key, new IndexStringMapper(key, indexKey));
}
- protected BaseMapping addIndexBooleanField(String key, String indexKey) {
- return addField(key, new IndexBooleanField(key, indexKey));
+ protected BaseMapping mapBoolean(String key, String indexKey) {
+ return map(key, new IndexBooleanMapper(key, indexKey));
}
- protected BaseMapping addIndexDatetimeField(String key, String indexKey) {
- return addField(key, new IndexDatetimeField(key, indexKey));
+ protected BaseMapping mapDateTime(String key, String indexKey) {
+ return map(key, new IndexDatetimeMapper(key, indexKey));
}
- protected BaseMapping addIndexArrayField(String key, String indexKey) {
- return addField(key, new IndexArrayField(key, indexKey));
+ protected BaseMapping mapArray(String key, String indexKey) {
+ return map(key, new IndexArrayMapper(key, indexKey));
}
- protected BaseMapping addField(String key, Field field) {
- fields.put(key, field);
- if (field instanceof IndexField) {
- IndexField indexField = (IndexField) field;
- indexFields.putAll(key, Arrays.asList(indexField.indexFields()));
+ protected BaseMapping map(String key, Mapper mapper) {
+ mappers.put(key, mapper);
+ if (mapper instanceof IndexMapper) {
+ IndexMapper indexField = (IndexMapper) mapper;
+ indexFieldsByWsFields.putAll(key, Arrays.asList(indexField.indexFields()));
}
return this;
}
- public static interface Field<D> {
- void write(JsonWriter json, D doc);
+ public static interface Mapper<DOC extends BaseDoc, CTX> {
+ void write(JsonWriter json, DOC doc, CTX context);
}
- public abstract static class IndexField<D> implements Field<D> {
+ public abstract static class IndexMapper<DOC extends BaseDoc, CTX> implements Mapper<DOC, CTX> {
protected final String[] indexFields;
- protected IndexField(String... indexFields) {
+ protected IndexMapper(String... indexFields) {
this.indexFields = indexFields;
}
/**
* String field
*/
- public static class IndexStringField extends IndexField<BaseDoc> {
+ public static class IndexStringMapper<DOC extends BaseDoc, CTX> extends IndexMapper<DOC,CTX> {
private final String key;
- public IndexStringField(String key, String indexKey, String defaultIndexKey) {
+ public IndexStringMapper(String key, String indexKey, String defaultIndexKey) {
super(indexKey, defaultIndexKey);
this.key = key;
}
- public IndexStringField(String key, String indexKey) {
+ public IndexStringMapper(String key, String indexKey) {
super(indexKey);
this.key = key;
}
@Override
- public void write(JsonWriter json, BaseDoc doc) {
+ public void write(JsonWriter json, DOC doc, CTX context) {
Object val = doc.getNullableField(indexFields[0]);
if (val == null && indexFields.length == 2) {
// There is an alternative value
}
}
- public static class IndexBooleanField extends IndexField<BaseDoc> {
+ public static class IndexBooleanMapper<DOC extends BaseDoc, CTX> extends IndexMapper<DOC,CTX> {
private final String key;
- public IndexBooleanField(String key, String indexKey) {
+ public IndexBooleanMapper(String key, String indexKey) {
super(indexKey);
this.key = key;
}
@Override
- public void write(JsonWriter json, BaseDoc doc) {
+ public void write(JsonWriter json, DOC doc, CTX context) {
Boolean val = doc.getNullableField(indexFields[0]);
json.prop(key, val != null ? val.booleanValue() : null);
}
}
- public static class IndexArrayField extends IndexField<BaseDoc> {
+ public static class IndexArrayMapper<DOC extends BaseDoc, CTX> extends IndexMapper<DOC,CTX> {
private final String key;
- public IndexArrayField(String key, String indexKey) {
+ public IndexArrayMapper(String key, String indexKey) {
super(indexKey);
this.key = key;
}
@Override
- public void write(JsonWriter json, BaseDoc doc) {
+ public void write(JsonWriter json, DOC doc, CTX context) {
Iterable<String> values = doc.getNullableField(indexFields[0]);
if (values != null) {
json.name(key).beginArray().values(values).endArray();
}
}
- public static class IndexDatetimeField extends IndexField<BaseDoc> {
+ public static class IndexDatetimeMapper<DOC extends BaseDoc, CTX> extends IndexMapper<DOC,CTX> {
private final String key;
- public IndexDatetimeField(String key, String indexKey) {
+ public IndexDatetimeMapper(String key, String indexKey) {
super(indexKey);
this.key = key;
}
@Override
- public void write(JsonWriter json, BaseDoc doc) {
+ public void write(JsonWriter json, DOC doc, CTX context) {
String val = doc.getNullableField(indexFields[0]);
if (val != null) {
json.propDateTime(key, IndexUtils.parseDateTime(val));
import org.junit.Test;
import org.sonar.api.resources.Languages;
+import org.sonar.api.server.debt.DebtModel;
import org.sonar.api.server.ws.internal.SimpleGetRequest;
import org.sonar.server.rule.index.RuleNormalizer;
import org.sonar.server.search.QueryOptions;
Languages languages = new Languages();
MacroInterpreter macroInterpreter = mock(MacroInterpreter.class);
+ DebtModel debtModel = mock(DebtModel.class);
@Test
public void toQueryOptions_load_all_fields() throws Exception {
- RuleMapping mapping = new RuleMapping(languages, macroInterpreter);
+ RuleMapping mapping = new RuleMapping(languages, macroInterpreter, debtModel);
SimpleGetRequest request = new SimpleGetRequest();
request.setParam("p", "1");
request.setParam("ps", "10");
@Test
public void toQueryOptions_load_only_few_simple_fields() throws Exception {
- RuleMapping mapping = new RuleMapping(languages, macroInterpreter);
+ RuleMapping mapping = new RuleMapping(languages, macroInterpreter, debtModel);
SimpleGetRequest request = new SimpleGetRequest();
request.setParam("p", "1");
request.setParam("ps", "10");
@Test
public void toQueryOptions_langName_requires_lang() throws Exception {
- RuleMapping mapping = new RuleMapping(languages, macroInterpreter);
+ RuleMapping mapping = new RuleMapping(languages, macroInterpreter, debtModel);
SimpleGetRequest request = new SimpleGetRequest();
request.setParam("p", "1");
request.setParam("ps", "10");
@Test
public void toQueryOptions_debt_requires_group_of_fields() throws Exception {
- RuleMapping mapping = new RuleMapping(languages, macroInterpreter);
+ RuleMapping mapping = new RuleMapping(languages, macroInterpreter, debtModel);
SimpleGetRequest request = new SimpleGetRequest();
request.setParam("p", "1");
request.setParam("ps", "10");
@Test
public void toQueryOptions_html_note_requires_markdown_note() throws Exception {
- RuleMapping mapping = new RuleMapping(languages, macroInterpreter);
+ RuleMapping mapping = new RuleMapping(languages, macroInterpreter, debtModel);
SimpleGetRequest request = new SimpleGetRequest();
request.setParam("p", "1");
request.setParam("ps", "10");
@Test
public void toQueryOptions_debt_characteristics() throws Exception {
- RuleMapping mapping = new RuleMapping(languages, macroInterpreter);
+ RuleMapping mapping = new RuleMapping(languages, macroInterpreter, debtModel);
SimpleGetRequest request = new SimpleGetRequest();
request.setParam("p", "1");
request.setParam("ps", "10");
assertThat(queryOptions.getFieldsToReturn()).containsOnly(
RuleNormalizer.RuleField.CHARACTERISTIC.field(),
- RuleNormalizer.RuleField.SUB_CHARACTERISTIC.field(),
- RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field(),
- RuleNormalizer.RuleField.DEFAULT_SUB_CHARACTERISTIC.field());
+ RuleNormalizer.RuleField.DEFAULT_CHARACTERISTIC.field());
}
}
MockUserSession.set();
WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD);
- request.setParam(SearchOptions.PARAM_FIELDS, "debtRemFn,debtChar");
+ request.setParam(SearchOptions.PARAM_FIELDS, "debtRemFn,debtChar,debtCharName");
WsTester.Result result = request.execute();
result.assertJson(this.getClass(), "search_debt_rule.json");
}
.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN)
.setLogin("me");
- CharacteristicDto characteristicDto = new CharacteristicDto().setKey("API").setName("API").setEnabled(true);
+ CharacteristicDto characteristicDto = new CharacteristicDto().setKey("API").setName("Api").setEnabled(true);
tester.get(CharacteristicDao.class).insert(characteristicDto, session);
CharacteristicDto subCharacteristicDto = new CharacteristicDto().setKey("API_ABUSE").setName("API Abuse").setEnabled(true).setParentId(characteristicDto.getId());
tester.get(CharacteristicDao.class).insert(subCharacteristicDto, session);
.setParam("key", ruleDto.getKey().toString());
WsTester.Result response = request.execute();
- System.out.println("response = " + response.outputAsString());
response.assertJson(getClass(), "show_rule_with_default_debt_infos.json", false);
}
.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN)
.setLogin("me");
- CharacteristicDto characteristicDto = new CharacteristicDto().setKey("API").setName("API").setEnabled(true);
+ CharacteristicDto characteristicDto = new CharacteristicDto().setKey("API").setName("Api").setEnabled(true);
tester.get(CharacteristicDao.class).insert(characteristicDto, session);
CharacteristicDto subCharacteristicDto = new CharacteristicDto().setKey("API_ABUSE").setName("API Abuse").setEnabled(true).setParentId(characteristicDto.getId());
tester.get(CharacteristicDao.class).insert(subCharacteristicDto, session);
.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN)
.setLogin("me");
- CharacteristicDto defaultCharacteristic = new CharacteristicDto().setKey("API").setName("API").setEnabled(true);
+ CharacteristicDto defaultCharacteristic = new CharacteristicDto().setKey("API").setName("Api").setEnabled(true);
tester.get(CharacteristicDao.class).insert(defaultCharacteristic, session);
CharacteristicDto defaultSubCharacteristic = new CharacteristicDto().setKey("API_ABUSE").setName("API Abuse").setEnabled(true).setParentId(defaultCharacteristic.getId());
tester.get(CharacteristicDao.class).insert(defaultSubCharacteristic, session);
- CharacteristicDto characteristic = new CharacteristicDto().setKey("OS").setName("OS").setEnabled(true);
+ CharacteristicDto characteristic = new CharacteristicDto().setKey("OS").setName("Os").setEnabled(true);
tester.get(CharacteristicDao.class).insert(characteristic, session);
CharacteristicDto subCharacteristic = new CharacteristicDto().setKey("OS_RELATED_PORTABILITY").setName("Portability").setEnabled(true).setParentId(characteristic.getId());
tester.get(CharacteristicDao.class).insert(subCharacteristic, session);
"status": "BETA",
"isTemplate": false,
"debtChar": "OS",
- "debtCharName": "OS",
+ "debtCharName": "Os",
"debtSubChar": "OS_RELATED_PORTABILITY",
- "debtSubCharName": "OS_RELATED_PORTABILITY",
+ "debtSubCharName": "Portability",
"debtRemFnType": "LINEAR_OFFSET",
"debtRemFnCoeff": "5d",
"debtRemFnOffset": "10h",
{
"rule": {
"debtChar": "API",
- "debtCharName": "API",
+ "debtCharName": "Api",
"debtSubChar": "API_ABUSE",
- "debtSubCharName": "API_ABUSE",
+ "debtSubCharName": "API Abuse",
"debtRemFnType": "LINEAR_OFFSET",
"debtRemFnCoeff": "5d",
"debtRemFnOffset": "10h",
"status": "BETA",
"isTemplate": false,
"debtChar": "API",
- "debtCharName": "API",
+ "debtCharName": "Api",
"debtSubChar": "API_ABUSE",
- "debtSubCharName": "API_ABUSE",
+ "debtSubCharName": "API Abuse",
"debtRemFnType": "LINEAR_OFFSET",
"debtRemFnCoeff": "5d",
"debtRemFnOffset": "10h",