Song.java

1
package com.github.dakusui.symfonion.song;
2
3
import com.github.dakusui.json.JsonException;
4
import com.github.dakusui.json.JsonUtils;
5
import com.github.dakusui.logias.Logias;
6
import com.github.dakusui.logias.lisp.Context;
7
import com.github.dakusui.symfonion.exceptions.ExceptionThrower;
8
import com.github.dakusui.symfonion.exceptions.SymfonionException;
9
import com.github.dakusui.symfonion.utils.Utils;
10
import com.github.dakusui.valid8j.Requires;
11
import com.google.gson.JsonArray;
12
import com.google.gson.JsonElement;
13
import com.google.gson.JsonObject;
14
15
import java.util.*;
16
17
import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.*;
18
import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.ContextKey.JSON_ELEMENT_ROOT;
19
import static com.github.dakusui.symfonion.exceptions.SymfonionTypeMismatchException.ARRAY;
20
import static com.github.dakusui.symfonion.exceptions.SymfonionTypeMismatchException.OBJECT;
21
import static com.github.dakusui.valid8j.Requires.requireNonNull;
22
23
public class Song {
24
25
  public static class Builder {
26
    private final Context logiasContext;
27
    private final JsonObject json;
28
29
    public Builder(Context logiasContext, JsonObject jsonObject) {
30
      this.logiasContext = requireNonNull(logiasContext);
31
      this.json = requireNonNull(jsonObject);
32
    }
33
34
    private static Context loadMidiDeviceProfile(JsonObject json, Context logiasContext) throws SymfonionException, JsonException {
35
      JsonElement tmp = JsonUtils.asJsonObjectWithDefault(json, new JsonObject(), Keyword.$settings);
36 1 1. loadMidiDeviceProfile : negated conditional → KILLED
      if (!tmp.isJsonObject()) {
37
        throw typeMismatchException(tmp, OBJECT);
38
      }
39
      String profileName = JsonUtils.asStringWithDefault(tmp.getAsJsonObject(), "", Keyword.$mididevice);
40
      Logias logias = new Logias(logiasContext);
41 1 1. loadMidiDeviceProfile : negated conditional → KILLED
      if (!"".equals(profileName)) {
42
        JsonObject deviceDef = JsonUtils.toJson(Utils.loadResource(profileName + ".json")).getAsJsonObject();
43
        Iterator<String> i = JsonUtils.keyIterator(deviceDef);
44 1 1. loadMidiDeviceProfile : negated conditional → NO_COVERAGE
        while (i.hasNext()) {
45
          String k = i.next();
46
          JsonElement v = deviceDef.get(k);
47
          logiasContext.bind(k, logias.run(logias.buildSexp(v)));
48
        }
49
      }
50 1 1. loadMidiDeviceProfile : replaced return value with null for com/github/dakusui/symfonion/song/Song$Builder::loadMidiDeviceProfile → SURVIVED
      return logiasContext;
51
    }
52
53
    private static List<Bar> initSequence(JsonObject json, Map<String, Groove> grooves, Map<String, Pattern> patterns) throws SymfonionException, JsonException {
54
      List<Bar> bars = new LinkedList<>();
55
      JsonElement tmp = JsonUtils.asJsonElement(json, Keyword.$sequence);
56 1 1. initSequence : negated conditional → KILLED
      if (!tmp.isJsonArray()) {
57
        throw typeMismatchException(tmp, ARRAY);
58
      }
59
      JsonArray seqJson = tmp.getAsJsonArray();
60
      int len = seqJson.getAsJsonArray().size();
61 2 1. initSequence : negated conditional → KILLED
2. initSequence : changed conditional boundary → KILLED
      for (int i = 0; i < len; i++) {
62
        JsonElement barJson = seqJson.get(i);
63 1 1. initSequence : negated conditional → KILLED
        if (!barJson.isJsonObject()) {
64
          throw typeMismatchException(seqJson, OBJECT);
65
        }
66
        Bar bar = new Bar(barJson.getAsJsonObject(), json, grooves, patterns);
67
        bars.add(bar);
68
      }
69 1 1. initSequence : replaced return value with Collections.emptyList for com/github/dakusui/symfonion/song/Song$Builder::initSequence → KILLED
      return bars;
70
    }
71
72
    private static Map<String, NoteMap> initNoteMaps(JsonObject json) throws SymfonionException, JsonException {
73
      Map<String, NoteMap> noteMaps = new HashMap<>();
74
      final JsonObject noteMapsJSON = JsonUtils.asJsonObjectWithDefault(json, new JsonObject(), Keyword.$notemaps);
75
76
      Iterator<String> i = JsonUtils.keyIterator(noteMapsJSON);
77
      noteMaps.put(Keyword.$normal.toString(), NoteMap.defaultNoteMap);
78
      noteMaps.put(Keyword.$percussion.toString(), NoteMap.defaultPercussionMap);
79 1 1. initNoteMaps : negated conditional → KILLED
      while (i.hasNext()) {
80
        String name = i.next();
81
        NoteMap cur = new NoteMap(JsonUtils.asJsonObject(noteMapsJSON, name));
82
        noteMaps.put(name, cur);
83
      }
84 1 1. initNoteMaps : replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initNoteMaps → KILLED
      return noteMaps;
85
    }
86
87
    private static Map<String, Pattern> initPatterns(JsonObject json, Map<String, NoteMap> noteMaps) throws SymfonionException, JsonException {
88
      Map<String, Pattern> patterns = new HashMap<>();
89
      JsonObject patternsJSON = JsonUtils.asJsonObjectWithDefault(json, new JsonObject(), Keyword.$patterns);
90
91
      Iterator<String> i = JsonUtils.keyIterator(patternsJSON);
92
      try (ExceptionThrower.Context ignored = context($(JSON_ELEMENT_ROOT, json))) {
93 1 1. initPatterns : negated conditional → KILLED
        while (i.hasNext()) {
94
          String name = i.next();
95
          Pattern cur = Pattern.createPattern(JsonUtils.asJsonObject(patternsJSON, name), noteMaps);
96
          patterns.put(name, cur);
97
        }
98
      }
99 1 1. initPatterns : replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initPatterns → KILLED
      return patterns;
100
    }
101
102
    private static Map<String, Part> initParts(JsonObject json) throws SymfonionException, JsonException {
103
      Map<String, Part> parts = new HashMap<>();
104 1 1. initParts : negated conditional → KILLED
      if (JsonUtils.hasPath(json, Keyword.$parts)) {
105
        JsonObject instrumentsJSON = JsonUtils.asJsonObject(json, Keyword.$parts);
106
        Iterator<String> i = JsonUtils.keyIterator(instrumentsJSON);
107 1 1. initParts : negated conditional → KILLED
        while (i.hasNext()) {
108
          String name = i.next();
109
          Part cur = new Part(name, JsonUtils.asJsonObject(instrumentsJSON, name));
110
          parts.put(name, cur);
111
        }
112
      }
113 1 1. initParts : replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initParts → KILLED
      return parts;
114
    }
115
116
    private static Map<String, Groove> initGrooves(JsonObject json) throws SymfonionException, JsonException {
117
      Map<String, Groove> grooves = new HashMap<>();
118 1 1. initGrooves : negated conditional → KILLED
      if (JsonUtils.hasPath(json, Keyword.$grooves)) {
119
        JsonObject groovesJSON = JsonUtils.asJsonObject(json, Keyword.$grooves);
120
121
        Iterator<String> i = JsonUtils.keyIterator(groovesJSON);
122 1 1. initGrooves : negated conditional → KILLED
        while (i.hasNext()) {
123
          String name = i.next();
124
          Groove cur = Groove.createGroove(JsonUtils.asJsonArray(groovesJSON, name));
125
          grooves.put(name, cur);
126
        }
127
      }
128 1 1. initGrooves : replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initGrooves → KILLED
      return grooves;
129
    }
130
131
    public Song build() throws JsonException, SymfonionException {
132
      try (ExceptionThrower.Context ignored = context($(JSON_ELEMENT_ROOT, json))) {
133
        Map<String, NoteMap> noteMaps = initNoteMaps(json);
134
        Map<String, Groove> grooves = initGrooves(json);
135
        Map<String, Pattern> patterns = initPatterns(json, noteMaps);
136
        return new Song(
137
            loadMidiDeviceProfile(json, logiasContext),
138
            initParts(this.json),
139
            patterns,
140
            noteMaps,
141
            grooves,
142
            initSequence(json, grooves, patterns)
143
        );
144
      }
145
    }
146
  }
147
148
  private final Context logiasContext;
149
  private final Map<String, Part> parts;
150
  private final Map<String, Pattern> patterns;
151
  private final Map<String, NoteMap> noteMaps;
152
  private final Map<String, Groove> grooves;
153
  private final List<Bar> bars;
154
155
156
  public Song(Context logiasContext,
157
              Map<String, Part> parts,
158
              Map<String, Pattern> patterns,
159
              Map<String, NoteMap> noteMaps,
160
              Map<String, Groove> grooves,
161
              List<Bar> bars
162
  ) {
163
    this.logiasContext = logiasContext;
164
    this.parts = Requires.requireNonNull(parts);
165
    this.patterns = Requires.requireNonNull(patterns);
166
    this.noteMaps = requireNonNull(noteMaps);
167
    this.grooves = requireNonNull(grooves);
168
    this.bars = requireNonNull(bars);
169
  }
170
171
172
  public Pattern pattern(String patternName) {
173 1 1. pattern : replaced return value with null for com/github/dakusui/symfonion/song/Song::pattern → NO_COVERAGE
    return this.patterns.get(patternName);
174
  }
175
176
  public NoteMap noteMap(String noteMapName) {
177 1 1. noteMap : replaced return value with null for com/github/dakusui/symfonion/song/Song::noteMap → NO_COVERAGE
    return this.noteMaps.get(noteMapName);
178
  }
179
180
  public List<Bar> bars() {
181 1 1. bars : replaced return value with Collections.emptyList for com/github/dakusui/symfonion/song/Song::bars → KILLED
    return Collections.unmodifiableList(this.bars);
182
  }
183
184
  public Set<String> partNames() {
185 1 1. partNames : replaced return value with Collections.emptySet for com/github/dakusui/symfonion/song/Song::partNames → KILLED
    return Collections.unmodifiableSet(this.parts.keySet());
186
  }
187
188
  public Part part(String name) {
189 1 1. part : replaced return value with null for com/github/dakusui/symfonion/song/Song::part → KILLED
    return this.parts.get(name);
190
  }
191
192
  public Context getLogiasContext() {
193 1 1. getLogiasContext : replaced return value with null for com/github/dakusui/symfonion/song/Song::getLogiasContext → SURVIVED
    return this.logiasContext;
194
  }
195
196
  public Groove groove(String grooveName) {
197 1 1. groove : replaced return value with null for com/github/dakusui/symfonion/song/Song::groove → NO_COVERAGE
    return this.grooves.get(grooveName);
198
  }
199
}

Mutations

36

1.1
Location : loadMidiDeviceProfile
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.invalid_01(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

41

1.1
Location : loadMidiDeviceProfile
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.invalid_01(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

44

1.1
Location : loadMidiDeviceProfile
Killed by : none
negated conditional → NO_COVERAGE

50

1.1
Location : loadMidiDeviceProfile
Killed by : none
replaced return value with null for com/github/dakusui/symfonion/song/Song$Builder::loadMidiDeviceProfile → SURVIVED

56

1.1
Location : initSequence
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_pattern(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

61

1.1
Location : initSequence
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_pattern(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

2.2
Location : initSequence
Killed by : com.github.dakusui.symfonion.tests.MidiCompilerTest.exercise[0: POSITIVE: given: 'top level attributes are all empty' when: 'compile' then: 'empty song'](com.github.dakusui.symfonion.tests.MidiCompilerTest)
changed conditional boundary → KILLED

63

1.1
Location : initSequence
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_pattern(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

69

1.1
Location : initSequence
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_parts(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
replaced return value with Collections.emptyList for com/github/dakusui/symfonion/song/Song$Builder::initSequence → KILLED

79

1.1
Location : initNoteMaps
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.invalid_01(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

84

1.1
Location : initNoteMaps
Killed by : com.github.dakusui.symfonion.tests.InvalidDataErrorTest.illegalNoteLength_02(com.github.dakusui.symfonion.tests.InvalidDataErrorTest)
replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initNoteMaps → KILLED

93

1.1
Location : initPatterns
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.invalid_01(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

99

1.1
Location : initPatterns
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_parts(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initPatterns → KILLED

104

1.1
Location : initParts
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.invalid_01(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

107

1.1
Location : initParts
Killed by : com.github.dakusui.symfonion.tests.MidiCompilerTest.exercise[0: POSITIVE: given: 'top level attributes are all empty' when: 'compile' then: 'empty song'](com.github.dakusui.symfonion.tests.MidiCompilerTest)
negated conditional → KILLED

113

1.1
Location : initParts
Killed by : com.github.dakusui.symfonion.tests.cli.subcommands.CompileTest.test(com.github.dakusui.symfonion.tests.cli.subcommands.CompileTest)
replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initParts → KILLED

118

1.1
Location : initGrooves
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.invalid_01(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
negated conditional → KILLED

122

1.1
Location : initGrooves
Killed by : com.github.dakusui.symfonion.tests.InvalidDataErrorTest.illegalNoteLength_01(com.github.dakusui.symfonion.tests.InvalidDataErrorTest)
negated conditional → KILLED

128

1.1
Location : initGrooves
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_pattern(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
replaced return value with Collections.emptyMap for com/github/dakusui/symfonion/song/Song$Builder::initGrooves → KILLED

173

1.1
Location : pattern
Killed by : none
replaced return value with null for com/github/dakusui/symfonion/song/Song::pattern → NO_COVERAGE

177

1.1
Location : noteMap
Killed by : none
replaced return value with null for com/github/dakusui/symfonion/song/Song::noteMap → NO_COVERAGE

181

1.1
Location : bars
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_parts(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
replaced return value with Collections.emptyList for com/github/dakusui/symfonion/song/Song::bars → KILLED

185

1.1
Location : partNames
Killed by : com.github.dakusui.symfonion.tests.cli.subcommands.CompileTest.test(com.github.dakusui.symfonion.tests.cli.subcommands.CompileTest)
replaced return value with Collections.emptySet for com/github/dakusui/symfonion/song/Song::partNames → KILLED

189

1.1
Location : part
Killed by : com.github.dakusui.symfonion.tests.cli.subcommands.CompileTest.test(com.github.dakusui.symfonion.tests.cli.subcommands.CompileTest)
replaced return value with null for com/github/dakusui/symfonion/song/Song::part → KILLED

193

1.1
Location : getLogiasContext
Killed by : none
replaced return value with null for com/github/dakusui/symfonion/song/Song::getLogiasContext → SURVIVED

197

1.1
Location : groove
Killed by : none
replaced return value with null for com/github/dakusui/symfonion/song/Song::groove → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.15.3