• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kit-data-manager / pit-service / #157

pending completion
#157

Pull #125

github-actions

web-flow
Merge 4f575b7a7 into 7470716c4
Pull Request #125: 114 Unclear/non-standard response for post api/v1/pit/pid

124 of 124 new or added lines in 11 files covered. (100.0%)

758 of 1377 relevant lines covered (55.05%)

0.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.8
/src/main/java/edu/kit/datamanager/pit/domain/PIDRecord.java
1
package edu.kit.datamanager.pit.domain;
2

3
import com.fasterxml.jackson.annotation.JsonIgnore;
4

5
import edu.kit.datamanager.pit.pidsystem.impl.local.PidDatabaseObject;
6

7
import java.util.ArrayList;
8
import java.util.Collection;
9
import java.util.HashMap;
10
import java.util.Iterator;
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Set;
14

15
/**
16
 * The internal representation for a PID record, offering methods to manipulate
17
 * the record.
18
 * 
19
 * While other representations exist, they are only used for easier database
20
 * communication or representation for the outside. In contrast, this is the
21
 * internal representation offering methods for manipulation.
22
 */
23
public class PIDRecord {
24

25
    private String pid = "";
1✔
26

27
    private Map<String, List<PIDRecordEntry>> entries = new HashMap<>();
1✔
28

29
    /**
30
     * Creates an empty record without PID.
31
     */
32
    public PIDRecord() {}
1✔
33

34
    /**
35
     * Creates a record with the same content as the given representation.
36
     * 
37
     * @param dbo the given record representation.
38
     */
39
    public PIDRecord(PidDatabaseObject dbo) {
1✔
40
        this.setPid(dbo.getPid());
1✔
41
        dbo.getEntries().entrySet().stream().forEach(entry -> {
1✔
42
            String key = entry.getKey();
1✔
43
            entry
1✔
44
                .getValue() // ArrayList<String>
1✔
45
                .stream()
1✔
46
                .forEach( value -> this.addEntry(key, "", value) );
1✔
47
        });
1✔
48
    }
1✔
49

50
    public PIDRecord(SimplePidRecord rec) {
1✔
51
        this.entries = new HashMap<>();
1✔
52
        for (SimplePair pair : rec.getPairs()) {
1✔
53
            this.addEntry(pair.getKey(), "", pair.getValue());
1✔
54
        }
1✔
55
    }
1✔
56

57
    /**
58
     * Convenience setter / builder method.
59
     * 
60
     * @param pid the pid to set in this object.
61
     * @return this object (builder method).
62
     */
63
    public PIDRecord withPID(String pid) {
64
        this.setPid(pid);
1✔
65
        return this;
1✔
66
    }
67

68
    public String getPid() {
69
        return pid;
1✔
70
    }
71

72
    public void setPid(String pid) {
73
        this.pid = pid;
1✔
74
    }
1✔
75

76
    public Map<String, List<PIDRecordEntry>> getEntries() {
77
        return entries;
1✔
78
    }
79

80
    public void setEntries(Map<String, List<PIDRecordEntry>> entries) {
81
        this.entries = entries;
1✔
82
    }
1✔
83

84
    /**
85
     * Adds a new key-name-value triplet.
86
     * 
87
     * @param propertyIdentifier the key/type PID.
88
     * @param propertyName the human-readable name for the given key/type.
89
     * @param propertyValue the value to this key/type.
90
     */
91
    public void addEntry(String propertyIdentifier, String propertyName, String propertyValue) {
92
        if (propertyIdentifier.isEmpty()) {
1✔
93
            throw new IllegalArgumentException("The identifier of a property may not be empty!");
1✔
94
        }
95
        PIDRecordEntry entry = new PIDRecordEntry();
1✔
96
        entry.setKey(propertyIdentifier);
1✔
97
        entry.setName(propertyName);
1✔
98
        entry.setValue(propertyValue);
1✔
99

100
        this.entries
1✔
101
            .computeIfAbsent(propertyIdentifier, key -> new ArrayList<>())
1✔
102
            .add(entry);
1✔
103
    }
1✔
104

105
    /**
106
     * Sets the name for a given key/type in all available pairs.
107
     * 
108
     * @param propertyIdentifier the key/type.
109
     * @param name the new name.
110
     */
111
    @JsonIgnore
112
    public void setPropertyName(String propertyIdentifier, String name) {
113
        List<PIDRecordEntry> propertyEntries = this.entries.get(propertyIdentifier);
×
114
        if (propertyEntries == null) {
×
115
            throw new IllegalArgumentException(
×
116
                "Property identifier not listed in this record: " + propertyIdentifier);
117
        }
118
        for (PIDRecordEntry entry : propertyEntries) {
×
119
            entry.setName(name);
×
120
        }
×
121
    }
×
122

123
    /**
124
     * Check if there is a pair or triplet containing the given property (key/type)
125
     * is availeble in this record.
126
     * 
127
     * @param propertyIdentifier the key/type to search for.
128
     * @return true, if the property/key/type is present.
129
     */
130
    public boolean hasProperty(String propertyIdentifier) {
131
        return entries.containsKey(propertyIdentifier);
1✔
132
    }
133

134
    /**
135
     * Removes all properties that are not listed in the given collection.
136
     *
137
     * @param propertiesToKeep a collection of property identifiers to keep.
138
     */
139
    public void removePropertiesNotListed(Collection<String> propertiesToKeep) {
140
        Iterator<String> iter = entries.keySet().iterator();
1✔
141
        while (iter.hasNext()) {
1✔
142
            String propID = iter.next();
1✔
143
            if (!propertiesToKeep.contains(propID)) {
1✔
144
                iter.remove();
×
145
            }
146
        }
1✔
147
    }
1✔
148

149
    /**
150
     * Returns all missing mandatory attributes from the given Profile, which are not
151
     * present in this record.
152
     * 
153
     * @param profile the given Profile definition.
154
     * @return all missing mandatory attributes.
155
     */
156
    public Collection<String> getMissingMandatoryTypesOf(TypeDefinition profile) {
157
        Collection<String> missing = new ArrayList<>();
1✔
158
        for (TypeDefinition td : profile.getSubTypes().values()) {
1✔
159
            String typePid = td.getIdentifier();
1✔
160
            if (!td.isOptional() && !this.entries.containsKey(typePid)) {
1✔
161
                missing.add(typePid);
1✔
162
            }
163
        }
1✔
164
        return missing;
1✔
165
    }
166

167
    /**
168
     * Get all properties contained in this record.
169
     * 
170
     * @return al contained properties.
171
     */
172
    @JsonIgnore
173
    public Set<String> getPropertyIdentifiers() {
174
        return entries.keySet();
1✔
175
    }
176

177
    /**
178
     * Get the value of the first element in case there are multiple elements
179
     * for the provided propertyIndentifier.
180
     */
181
    public String getPropertyValue(String propertyIdentifier) {
182
        List<PIDRecordEntry> entry = entries.get(propertyIdentifier);
1✔
183
        if (entry == null) {
1✔
184
            throw new IllegalArgumentException("Property identifier not listed in this record: " + propertyIdentifier);
×
185
        }
186
        return entry.get(0).getValue();
1✔
187
    }
188

189
    /**
190
     * Get all values of a given property.
191
     * 
192
     * @param propertyIdentifier the given property identifier.
193
     * @return all values of the given property.
194
     */
195
    public String[] getPropertyValues(String propertyIdentifier) {
196
        List<PIDRecordEntry> entry = entries.get(propertyIdentifier);
1✔
197
        if (entry == null) {
1✔
198
            throw new IllegalArgumentException("Property identifier not listed in this record: " + propertyIdentifier);
×
199
        }
200

201
        List<String> values = new ArrayList<>();
1✔
202
        for (PIDRecordEntry e : entry) {
1✔
203
            values.add(e.getValue());
1✔
204
        }
1✔
205
        return values.toArray(new String[] {});
1✔
206
    }
207

208
    @Override
209
    public int hashCode() {
210
        final int prime = 31;
×
211
        int result = 1;
×
212
        result = prime * result + ((pid == null) ? 0 : pid.hashCode());
×
213
        result = prime * result + ((entries == null) ? 0 : entries.hashCode());
×
214
        return result;
×
215
    }
216

217
    /**
218
     * Checks if two PIDRecords are equivalent.
219
     * 
220
     * - Ignores the name attribute: Only keys and values matter.
221
     * - Ignores order of keys or values
222
     */
223
    @Override
224
    public boolean equals(Object obj) {
225
        if (this == obj) {return true;}
1✔
226
        if (obj == null) {return false;}
1✔
227
        if (getClass() != obj.getClass()) {return false;}
1✔
228

229
        PIDRecord other = (PIDRecord) obj;
1✔
230
        if (pid == null) {
1✔
231
            if (other.pid != null) {return false;}
×
232
        } else if (!pid.equals(other.pid)) {
1✔
233
            return false;
×
234
        }
235

236
        if (this.entries == null) {
1✔
237
            return other.entries == null;
×
238
        } else if (other.entries == null) {
1✔
239
            return this.entries == null;
×
240
        } else {
241
            // Equal means:
242
            // 1. have the same set of keys
243
            boolean isEqual = this.entries.keySet().equals(other.getEntries().keySet());
1✔
244
            if (!isEqual) {return false;}
1✔
245
            // 2. for each key, have the same values (order does not matter)
246
            isEqual &= this.entries.values().stream()
1✔
247
                .flatMap(List<PIDRecordEntry>::stream)
1✔
248
                .filter(entry -> other.entries.get(entry.getKey()).stream()
1✔
249
                    .filter(otherEntry -> otherEntry.getValue().equals(entry.getValue()))
1✔
250
                    .count() == 0 // keep key-value-pairs with values not present in `other`.
1✔
251
                )
252
                .count() == 0; // there should be no pairs with values which are not available in `other`.
1✔
253
            return isEqual;
1✔
254
        }
255
    }
256

257
    @Override
258
    public String toString() {
259
        return "PIDRecord [pid=" + pid + ", entries=" + entries + "]";
×
260
    }
261
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc