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

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

13 Nov 2023 05:22PM UTC coverage: 72.606% (+11.8%) from 60.79%
#324

push

github

web-flow
Merge pull request #174 from kit-data-manager/dev-v2

Development branch for v2.0.0

136 of 205 new or added lines in 14 files covered. (66.34%)

4 existing lines in 3 files now uncovered.

872 of 1201 relevant lines covered (72.61%)

0.73 hits per line

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

89.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.entities.EtagSupport;
6
import edu.kit.datamanager.pit.pidsystem.impl.local.PidDatabaseObject;
7

8
import java.util.ArrayList;
9
import java.util.Collection;
10
import java.util.HashMap;
11
import java.util.Iterator;
12
import java.util.List;
13
import java.util.Map;
14
import java.util.stream.Collectors;
15
import java.util.Set;
16

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

27
    private String pid = "";
1✔
28

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

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

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

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

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

70
    public String getPid() {
71
        return pid;
1✔
72
    }
73

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

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

82
    @JsonIgnore
83
    public Set<SimplePair> getSimpleEntries() {
84
        return this.entries
1✔
85
                .entrySet()
1✔
86
                .stream()
1✔
87
                .flatMap(
1✔
88
                        entry -> entry.getValue().stream()
1✔
89
                                .map(complexPair -> new SimplePair(complexPair.getKey(), complexPair.getValue())))
1✔
90
                .collect(Collectors.toSet());
1✔
91
    }
92

93
    public void setEntries(Map<String, List<PIDRecordEntry>> entries) {
94
        this.entries = entries;
1✔
95
    }
1✔
96

97
    /**
98
     * Adds a new key-name-value triplet.
99
     * 
100
     * @param propertyIdentifier the key/type PID.
101
     * @param propertyName the human-readable name for the given key/type.
102
     * @param propertyValue the value to this key/type.
103
     */
104
    public void addEntry(String propertyIdentifier, String propertyName, String propertyValue) {
105
        if (propertyIdentifier.isEmpty()) {
1✔
106
            throw new IllegalArgumentException("The identifier of a property may not be empty!");
1✔
107
        }
108
        PIDRecordEntry entry = new PIDRecordEntry();
1✔
109
        entry.setKey(propertyIdentifier);
1✔
110
        entry.setName(propertyName);
1✔
111
        entry.setValue(propertyValue);
1✔
112

113
        this.entries
1✔
114
            .computeIfAbsent(propertyIdentifier, key -> new ArrayList<>())
1✔
115
            .add(entry);
1✔
116
    }
1✔
117

118
    /**
119
     * Sets the name for a given key/type in all available pairs.
120
     * 
121
     * @param propertyIdentifier the key/type.
122
     * @param name the new name.
123
     */
124
    @JsonIgnore
125
    public void setPropertyName(String propertyIdentifier, String name) {
NEW
126
        List<PIDRecordEntry> propertyEntries = this.entries.get(propertyIdentifier);
×
NEW
127
        if (propertyEntries == null) {
×
NEW
128
            throw new IllegalArgumentException(
×
129
                "Property identifier not listed in this record: " + propertyIdentifier);
130
        }
NEW
131
        for (PIDRecordEntry entry : propertyEntries) {
×
132
            entry.setName(name);
×
133
        }
×
134
    }
×
135

136
    /**
137
     * Check if there is a pair or triplet containing the given property (key/type)
138
     * is availeble in this record.
139
     * 
140
     * @param propertyIdentifier the key/type to search for.
141
     * @return true, if the property/key/type is present.
142
     */
143
    public boolean hasProperty(String propertyIdentifier) {
144
        return entries.containsKey(propertyIdentifier);
1✔
145
    }
146

147
    /**
148
     * Removes all properties that are not listed in the given collection.
149
     *
150
     * @param propertiesToKeep a collection of property identifiers to keep.
151
     */
152
    public void removePropertiesNotListed(Collection<String> propertiesToKeep) {
153
        Iterator<String> iter = entries.keySet().iterator();
1✔
154
        while (iter.hasNext()) {
1✔
155
            String propID = iter.next();
1✔
156
            if (!propertiesToKeep.contains(propID)) {
1✔
157
                iter.remove();
×
158
            }
159
        }
1✔
160
    }
1✔
161

162
    /**
163
     * Returns all missing mandatory attributes from the given Profile, which are not
164
     * present in this record.
165
     * 
166
     * @param profile the given Profile definition.
167
     * @return all missing mandatory attributes.
168
     */
169
    public Collection<String> getMissingMandatoryTypesOf(TypeDefinition profile) {
170
        Collection<String> missing = new ArrayList<>();
1✔
171
        for (TypeDefinition td : profile.getSubTypes().values()) {
1✔
172
            String typePid = td.getIdentifier();
1✔
173
            if (!td.isOptional() && !this.entries.containsKey(typePid)) {
1✔
174
                missing.add(typePid);
1✔
175
            }
176
        }
1✔
177
        return missing;
1✔
178
    }
179

180
    /**
181
     * Get all properties contained in this record.
182
     * 
183
     * @return al contained properties.
184
     */
185
    @JsonIgnore
186
    public Set<String> getPropertyIdentifiers() {
187
        return entries.keySet();
1✔
188
    }
189

190
    /**
191
     * Get the value of the first element in case there are multiple elements
192
     * for the provided propertyIndentifier.
193
     */
194
    public String getPropertyValue(String propertyIdentifier) {
195
        List<PIDRecordEntry> entry = entries.get(propertyIdentifier);
1✔
196
        if (entry == null) {
1✔
197
            return "";
×
198
        }
199
        return entry.get(0).getValue();
1✔
200
    }
201

202
    /**
203
     * Get all values of a given property.
204
     * 
205
     * @param propertyIdentifier the given property identifier.
206
     * @return all values of the given property.
207
     */
208
    public String[] getPropertyValues(String propertyIdentifier) {
209
        List<PIDRecordEntry> entry = entries.get(propertyIdentifier);
1✔
210
        if (entry == null) {
1✔
211
            return new String[]{};
1✔
212
        }
213

214
        List<String> values = new ArrayList<>();
1✔
215
        for (PIDRecordEntry e : entry) {
1✔
216
            values.add(e.getValue());
1✔
217
        }
1✔
218
        return values.toArray(new String[] {});
1✔
219
    }
220

221
    @Override
222
    public int hashCode() {
223
        final int prime = 31;
1✔
224
        int result = 1;
1✔
225
        result = prime * result + ((pid == null) ? 0 : pid.hashCode());
1✔
226
        Set<SimplePair> simpleEntries = this.getSimpleEntries();
1✔
227
        result = prime * result + ((simpleEntries == null) ? 0 : simpleEntries.hashCode());
1✔
228
        return result;
1✔
229
    }
230

231
    /**
232
     * Checks if two PIDRecords are equivalent.
233
     * 
234
     * - Ignores the name attribute: Only keys and values matter.
235
     * - Ignores order of keys or values
236
     */
237
    @Override
238
    public boolean equals(Object obj) {
239
        if (this == obj) {return true;}
1✔
240
        if (obj == null) {return false;}
1✔
241
        if (getClass() != obj.getClass()) {return false;}
1✔
242

243
        PIDRecord other = (PIDRecord) obj;
1✔
244
        boolean isThisPidEmpty = pid == null || pid.isBlank();
1✔
245
        boolean isOtherPidEmpty = other.pid == null || other.pid.isBlank();
1✔
246
        boolean isBothPidEmpty = isThisPidEmpty && isOtherPidEmpty;
1✔
247
        boolean equalPIDs = isBothPidEmpty || (this.pid != null && this.pid.equals(other.pid));
1✔
248

249
        if (!equalPIDs) {
1✔
250
            return false;
1✔
251
        }
252

253
        // this ignores attributes order, names, and even duplicates
254
        return this.getSimpleEntries().equals(other.getSimpleEntries());
1✔
255
    }
256

257
    @Override
258
    public String toString() {
NEW
259
        return "PIDRecord [pid=" + pid + ", entries=" + entries + "]";
×
260
    }
261

262
    /**
263
     * Calculates an etag for a record.
264
     * 
265
     * @return an etag, which is independent of any order or duplicates in the
266
     *         entries.
267
     */
268
    @JsonIgnore
269
    @Override
270
    public String getEtag() {
271
        return Integer.toString(this.hashCode());
1✔
272
    }
273
}
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

© 2026 Coveralls, Inc