[32] | 1 | import "../libraries/decent/common.eol"; |
---|
| 2 | import "../libraries/decent/logging.eol"; |
---|
| 3 | import "../libraries/arff/common.eol"; |
---|
| 4 | |
---|
| 5 | var selectedType = Native("java.lang.System").getProperty("epsilon.transformation.decent2arffx.type"); |
---|
| 6 | var skipSource = Native("java.lang.System").getProperty("epsilon.transformation.decent2arffx.skipSource").asBoolean(); |
---|
| 7 | |
---|
| 8 | var Type = DECENT!ArtifactType.allInstances().select(a|a.name = selectedType).first(); |
---|
| 9 | if (Type.isUndefined()) { |
---|
| 10 | //handle wrong arguments here ? |
---|
| 11 | } |
---|
| 12 | |
---|
| 13 | var types = new OrderedSet(); |
---|
| 14 | types.add("code"); |
---|
| 15 | //types.add("Class"); |
---|
| 16 | //types.add("Method"); |
---|
| 17 | //types.add("Function"); |
---|
| 18 | //types.add("Module"); |
---|
| 19 | |
---|
| 20 | //TODO: move to common, use for tagging states? |
---|
| 21 | var nestedAnonymousClassFilter = "\"[\\w]+\\$[\\d]+.*\""; |
---|
| 22 | |
---|
| 23 | var Model = DECENT!Model.allInstances().first(); |
---|
| 24 | |
---|
| 25 | var TouchCountAttribute = addAttribute("TouchCount", "Number of touches to an artifact"); |
---|
| 26 | var ArtifactCountAttribute = addAttribute("ArtifactCount", "Number of known artifacts of the same type"); |
---|
| 27 | var AuthorCountAttribute = addAttribute("AuthorCount", "Number of known authors for an artifact up to the current state"); |
---|
| 28 | var GlobalAuthorCountAttribute = addAttribute("GlobalAuthorCount", "Number of known authors for all artifacts up to the current state"); |
---|
| 29 | var FileCountAttribute = addAttribute("FileCount", "Number of existing artifacts up to the current state"); |
---|
| 30 | |
---|
| 31 | "Running preprocess".log(1); |
---|
| 32 | var start = Native("java.lang.System").currentTimeMillis(); |
---|
| 33 | |
---|
| 34 | for (type in types) { |
---|
| 35 | ("Processing type "+type).log(1); |
---|
| 36 | preprocessArtifacts(type); |
---|
| 37 | } |
---|
| 38 | updateDeltas(); |
---|
| 39 | |
---|
| 40 | |
---|
| 41 | var end = Native("java.lang.System").currentTimeMillis(); |
---|
| 42 | var duration = end - start; |
---|
| 43 | ("Duration: "+duration.toMinutes().round(5)).log(1); |
---|
| 44 | |
---|
| 45 | |
---|
| 46 | operation updateDeltas() { |
---|
| 47 | for (a in DECENT!Artifact.allInstances()) { |
---|
| 48 | (""+a.name).log(3); |
---|
| 49 | for (s in a.states.select(x|x.isHit())) { |
---|
| 50 | for (v in s.values.select(v|v.isTypeOf(DoubleValue) or v.isTypeOf(IntegerValue))) { |
---|
| 51 | ("["+a.type.name+"]"+a.name+"@"+s.ID+"::"+v.ofAttribute.name).log(4); |
---|
| 52 | s.fromActivity.get(0).addDelta(v.ofAttribute); |
---|
| 53 | } |
---|
| 54 | } |
---|
| 55 | } |
---|
| 56 | } |
---|
| 57 | |
---|
| 58 | operation preprocessArtifacts(typeName : String) { |
---|
| 59 | var type = DECENT!ArtifactType.allInstances().select(t|t.name = typeName).first(); |
---|
| 60 | if (type.isUndefined()) { |
---|
| 61 | //TODO: check that type is set |
---|
| 62 | //handle wrong arguments here ? |
---|
| 63 | return; |
---|
| 64 | } |
---|
| 65 | |
---|
| 66 | var artifacts = Artifact.allInstances().select(x|x.type = type and not x.name.matches(nestedAnonymousClassFilter)).sortBy(x|x.name); |
---|
| 67 | |
---|
| 68 | var artifactDevelopers = new Set(); |
---|
| 69 | |
---|
| 70 | |
---|
| 71 | for (a in artifacts) { |
---|
| 72 | var sCount = 0; |
---|
| 73 | for (s in a.states.select(x|x.isHit()).sortBy(x|x.ID)) { |
---|
| 74 | ("Processing ["+a.type.name+"]"+a.name+"@"+s.ID).log(4); |
---|
| 75 | sCount = sCount+1; |
---|
| 76 | s.addValue(TouchCountAttribute, sCount); |
---|
| 77 | |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | |
---|
| 81 | |
---|
| 82 | // Count artifacts and put existing ones in filecount value |
---|
| 83 | var existingArtifacts = artifacts.select(x|x.states.select(y|y.fromActivity.first().date.time <= s.fromActivity.first().date.time).size() > 0); |
---|
| 84 | var fileCount = existingArtifacts.size(); |
---|
| 85 | s.addValue(FileCountAttribute, fileCount); |
---|
| 86 | |
---|
| 87 | //this refers more to the state of the project at a given point in time |
---|
| 88 | //thus the information will be identical in all states of artifacts with the same state.ID |
---|
| 89 | //perhaps it should be calculated during the export rather than stored in the model |
---|
| 90 | //(note however that it is still artifact type related) |
---|
| 91 | var aCount = artifacts.select(x|x.states.select(y|y.fromActivity.first().date <= s.fromActivity.first().date).size() > 0).size(); |
---|
| 92 | //(a.name+"@"+s.ID+ " -> Number of known artifacts of type "+a.type.name+": "+aCount).println(); |
---|
| 93 | s.addValue(ArtifactCountAttribute, aCount); |
---|
| 94 | |
---|
| 95 | //author count, could also be calculated from all the activities for an artifact up to a point |
---|
| 96 | artifactDevelopers.add(s.fromActivity.first().agent); |
---|
| 97 | var dCount = artifactDevelopers.size(); |
---|
| 98 | s.addValue(AuthorCountAttribute, dCount); |
---|
| 99 | |
---|
| 100 | //number of all known developers up to the point |
---|
| 101 | //NOT restricted to the type of interest!!! |
---|
| 102 | DECENT!Agent.allInstances().select(x|x.activities.select(y|y.date <= s.fromActivity.first().date).size() > 0).size(); |
---|
| 103 | var gdCount = artifactDevelopers.size(); |
---|
| 104 | s.addValue(GlobalAuthorCountAttribute, gdCount); |
---|
| 105 | } |
---|
| 106 | artifactDevelopers.clear(); |
---|
| 107 | } |
---|
| 108 | |
---|
| 109 | ("Processing to arffx ...").log(2); |
---|
| 110 | |
---|
| 111 | var arffx = new ARFFx!Model(); |
---|
| 112 | arffx.name = Model.name+"-artifacts-"+type.name; |
---|
| 113 | arffx.meta.put("DECENT.ArtifactType", type.name); |
---|
| 114 | arffx.meta.put("ARFFx.Type", "artifact"); |
---|
| 115 | |
---|
| 116 | for (a in artifacts) { |
---|
| 117 | (" Artifact " +a.name).log(3); |
---|
| 118 | |
---|
| 119 | //we exclude first and last states! |
---|
| 120 | //careful with the filtering here... |
---|
| 121 | // for (s in a.states.excluding(a.states.first()).excluding(a.states.last()).select(x|x.isHit() and x.next.first().isHit()).sortBy(x|x.ID)) { |
---|
| 122 | for (s in a.states.excluding(a.states.first()).select(x|x.isHit()).sortBy(x|x.ID)) { |
---|
| 123 | s.processTargetState(arffx); |
---|
| 124 | } |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | //on transformation to Weka instances - either transform to ARFFx and then use Java EMF API on ARFFx |
---|
| 128 | //or use Java EMF API on DECENT |
---|
| 129 | } |
---|
| 130 | |
---|
| 131 | |
---|
| 132 | operation DECENT!State processTargetState (arffx : ARFFx!Model) { |
---|
| 133 | var p = self.previous.first(); |
---|
| 134 | while (p.isDefined() and not p.isHit()) { |
---|
| 135 | //TODO: what if more than one? |
---|
| 136 | p = p.previous.first(); |
---|
| 137 | } |
---|
| 138 | if (p.isDefined() or skipSource){ |
---|
| 139 | |
---|
| 140 | var i = new ARFFx!Instance(); |
---|
| 141 | arffx.data.add(i); |
---|
| 142 | |
---|
| 143 | i.addValue('\"'+self.artifact.name.asString()+'\"', "Artifact.Name"); |
---|
| 144 | i.addValue(self.ID.asString(), "Artifact.Target.StateID"); |
---|
| 145 | i.addValue('\"'+self.fromActivity.first().agent.name+'\"', "Agent.Name"); |
---|
| 146 | |
---|
| 147 | for (v in self.values.select(x|x.isTypeOf(DECENT!DoubleValue) or x.isTypeOf(DECENT!IntegerValue))) { |
---|
| 148 | i.addValue(v.content.asString(), "Artifact.Target."+v.name); |
---|
| 149 | } |
---|
| 150 | |
---|
| 151 | var ax = self.fromActivity.first(); |
---|
| 152 | |
---|
| 153 | //TODO: add activity meta-data |
---|
| 154 | for (v in ax.values.select(x|x.isTypeOf(DECENT!DoubleValue) or x.isTypeOf(DECENT!IntegerValue))) { |
---|
| 155 | i.addValue(v.content.asString(), "Activity."+v.name); |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | for (v in ax.deltas) { |
---|
| 159 | i.addValue(v.change.asString(), "Artifact.Delta."+v.onAttribute.name); |
---|
| 160 | } |
---|
| 161 | |
---|
| 162 | //TODO: these are notably missing in several places! |
---|
| 163 | if (ax.agentState.isDefined()) { |
---|
| 164 | for (v in ax.agentState.values.select(x|x.isTypeOf(DECENT!DoubleValue) or x.isTypeOf(DECENT!IntegerValue))) { |
---|
| 165 | //i.addValue(v.content.asString(), "Agent."+v.name); |
---|
| 166 | } |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | if (not skipSource) { |
---|
| 170 | i.addValue(p.ID.asString(), "Artifact.Source.StateID"); |
---|
| 171 | |
---|
| 172 | for (v in p.values.select(x|x.isTypeOf(DECENT!DoubleValue) or x.isTypeOf(DECENT!IntegerValue))) { |
---|
| 173 | i.addValue(v.content.asString(), "Artifact.Source."+v.name); |
---|
| 174 | } |
---|
| 175 | } |
---|
| 176 | } else { |
---|
| 177 | } |
---|
| 178 | } |
---|