Skip to content

Commit 201054e

Browse files
authored
Merge pull request #22 from Jalen-Stephens/9-service-implement-imageservice-core-logic
9 service implement imageservice core logic
2 parents 95fc434 + 94d1005 commit 201054e

File tree

8 files changed

+655
-18
lines changed

8 files changed

+655
-18
lines changed

citations.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,3 +726,114 @@ Guidance on finalizing Spring Security JWT resource server configuration for Sup
726726
> Portions of this commit or configuration were generated with assistance from OpenAI ChatGPT (GPT-5) on October 21, 2025. All AI-generated content was reviewed, verified, and finalized by the development team.
727727
728728
---
729+
730+
### **Commit / Ticket Reference**
731+
732+
* **Commit:** `feat(#9): add ImageRepository and implement ImageService with ownership and service-layer exceptions`
733+
* **Ticket:** `#9 — Implement ImageService core logic`
734+
* **Date:** October 22, 2025
735+
* **Team Member:** Jalen Stephens
736+
737+
---
738+
739+
### **AI Tool Information**
740+
741+
* **Tool Used:** OpenAI ChatGPT (GPT-5)
742+
* **Access Method:** ChatGPT Web (.edu academic access)
743+
* **Configuration:** Default model settings
744+
* **Cost:** $0 (no paid API calls)
745+
746+
---
747+
748+
### **Purpose of AI Assistance**
749+
750+
The AI provided guidance and implementation help for creating the `ImageRepository`, wiring it into the `ImageService`, and introducing service-layer exceptions (`NotFoundException`, `ForbiddenException`) to support ownership enforcement and clean error semantics.
751+
752+
---
753+
754+
### **Prompts / Interaction Summary**
755+
756+
* Asked how to start on the ImageService ticket.
757+
* Shared existing schema for the `images` table.
758+
* Requested matching repository + service implementation.
759+
* Asked whether service-layer exceptions are standard practice.
760+
* Requested a one-line commit message referencing ticket `#9`.
761+
762+
---
763+
764+
### **Resulting Artifacts**
765+
766+
* `ImageRepository.java` (new)
767+
* `ImageService.java` (updated core logic + ownership enforcement)
768+
* `ForbiddenException.java` (new)
769+
* `NotFoundException.java` (new)
770+
771+
---
772+
773+
### **Verification**
774+
775+
* Build completed successfully using `mvn clean verify`.
776+
* Code reviewed manually to confirm schema alignment and method signatures.
777+
* Successfully wired into the service layer with no startup issues.
778+
779+
---
780+
781+
### **Attribution Statement**
782+
783+
> Portions of this commit or configuration were generated with assistance from OpenAI ChatGPT (GPT-5) on October 22, 2025. All AI-generated content was reviewed, verified, and finalized by the development team.
784+
785+
---
786+
787+
### **Commit / Ticket Reference**
788+
789+
* **Commit:** `test(#9): add ImageService unit tests and update pom to run under Java 17`
790+
* **Ticket:** `#9 — Implement ImageService core logic`
791+
* **Date:** October 22, 2025
792+
* **Team Member:** Jalen Stephens
793+
794+
---
795+
796+
### **AI Tool Information**
797+
798+
* **Tool Used:** OpenAI ChatGPT (GPT-5)
799+
* **Access Method:** ChatGPT Web (.edu academic access)
800+
* **Configuration:** Default model settings
801+
* **Cost:** $0 (no paid API calls)
802+
803+
---
804+
805+
### **Purpose of AI Assistance**
806+
807+
Assistance was used to design and implement comprehensive branch-coverage unit tests for `ImageService`, including mocking strategies, repository interaction expectations, and handling JDK/Jacoco compatibility issues for coverage instrumentation.
808+
809+
---
810+
811+
### **Prompts / Interaction Summary**
812+
813+
* “Can we create unit test now on the code we just added…”
814+
* Debugging JaCoCo crash and version mismatch
815+
* Fixing Mockito inline instrumentation conflict
816+
* Request for one-line commit message referencing #9
817+
818+
---
819+
820+
### **Resulting Artifacts**
821+
822+
* `src/test/java/dev/coms4156/project/metadetect/service/ImageServiceTest.java`
823+
* Updated `pom.xml` (ensuring Java 17 execution for tests/coverage)
824+
825+
---
826+
827+
### **Verification**
828+
829+
* Successfully executed `mvn clean test` under Java 17
830+
* Verified branch coverage logic (success + failure paths)
831+
* Confirmed green test suite and valid JaCoCo run
832+
833+
---
834+
835+
### **Attribution Statement**
836+
837+
> Portions of this commit or configuration were generated with assistance from OpenAI ChatGPT (GPT-5) on October 22, 2025. All AI-generated content was reviewed, verified, and finalized by the development team.
838+
839+
---

pom.xml

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,23 @@
147147
</extensions>
148148
<finalName>${project.artifactId}-${project.version}</finalName>
149149
<plugins>
150+
<!-- Spring Boot (single declaration) -->
150151
<plugin>
151152
<groupId>org.springframework.boot</groupId>
152153
<artifactId>spring-boot-maven-plugin</artifactId>
154+
<configuration>
155+
<jvmArguments>--enable-native-access=ALL-UNNAMED</jvmArguments>
156+
</configuration>
157+
<executions>
158+
<execution>
159+
<goals>
160+
<goal>repackage</goal>
161+
</goals>
162+
</execution>
163+
</executions>
153164
</plugin>
154165

155-
<!-- Checkstyle (already configured to run at validate) -->
166+
<!-- Checkstyle -->
156167
<plugin>
157168
<groupId>org.apache.maven.plugins</groupId>
158169
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -168,12 +179,14 @@
168179
<execution>
169180
<id>validate</id>
170181
<phase>validate</phase>
171-
<goals><goal>check</goal></goals>
182+
<goals>
183+
<goal>check</goal>
184+
</goals>
172185
</execution>
173186
</executions>
174187
</plugin>
175188

176-
<!-- PMD static analysis -->
189+
<!-- PMD -->
177190
<plugin>
178191
<groupId>org.apache.maven.plugins</groupId>
179192
<artifactId>maven-pmd-plugin</artifactId>
@@ -185,12 +198,14 @@
185198
<executions>
186199
<execution>
187200
<phase>verify</phase>
188-
<goals><goal>check</goal></goals>
201+
<goals>
202+
<goal>check</goal>
203+
</goals>
189204
</execution>
190205
</executions>
191206
</plugin>
192207

193-
<!-- JaCoCo coverage -->
208+
<!-- JaCoCo -->
194209
<plugin>
195210
<groupId>org.jacoco</groupId>
196211
<artifactId>jacoco-maven-plugin</artifactId>
@@ -201,12 +216,9 @@
201216
<goal>prepare-agent</goal>
202217
</goals>
203218
<configuration>
204-
<!-- Instrument ONLY our code -->
205219
<includes>
206-
<include>dev/coms4156/project/metadetect/*</include>
207220
<include>dev/coms4156/project/metadetect/**</include>
208221
</includes>
209-
<!-- Make sure we don't try to touch JDK or Spring classes -->
210222
<excludes>
211223
<exclude>java/**</exclude>
212224
<exclude>jdk/**</exclude>
@@ -215,7 +227,6 @@
215227
</excludes>
216228
</configuration>
217229
</execution>
218-
219230
<execution>
220231
<id>report</id>
221232
<phase>verify</phase>
@@ -225,13 +236,6 @@
225236
</execution>
226237
</executions>
227238
</plugin>
228-
<plugin>
229-
<groupId>org.springframework.boot</groupId>
230-
<artifactId>spring-boot-maven-plugin</artifactId>
231-
<configuration>
232-
<jvmArguments>--enable-native-access=ALL-UNNAMED</jvmArguments>
233-
</configuration>
234-
</plugin>
235239
</plugins>
236240
</build>
237241
</project>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package dev.coms4156.project.metadetect.model;
2+
3+
import java.time.Instant;
4+
import java.util.UUID;
5+
import org.springframework.data.annotation.Id;
6+
import org.springframework.data.relational.core.mapping.Column;
7+
import org.springframework.data.relational.core.mapping.Table;
8+
9+
/**
10+
* Represents an uploaded image belonging to a user.
11+
* Each image stores metadata such as filename, optional labels,
12+
* storage location, and its upload timestamp.
13+
*/
14+
@Table("images")
15+
public class Image {
16+
17+
@Id
18+
private UUID id;
19+
20+
@Column("user_id")
21+
private UUID userId;
22+
23+
@Column("filename")
24+
private String filename;
25+
26+
@Column("storage_path")
27+
private String storagePath;
28+
29+
@Column("labels")
30+
private String[] labels;
31+
32+
@Column("note")
33+
private String note;
34+
35+
@Column("uploaded_at")
36+
private Instant uploadedAt;
37+
38+
public Image() {}
39+
40+
/**
41+
* Constructs a new Image record.
42+
*
43+
* @param id unique identifier of the image
44+
* @param userId id of the owning user
45+
* @param filename original filename from the upload
46+
* @param storagePath path of the stored file (if present)
47+
* @param labels optional labels (Postgres text[])
48+
* @param note user note attached to the image
49+
* @param uploadedAt timestamp when the image was uploaded
50+
*/
51+
public Image(UUID id, UUID userId, String filename, String storagePath,
52+
String[] labels, String note, Instant uploadedAt) {
53+
this.id = id;
54+
this.userId = userId;
55+
this.filename = filename;
56+
this.storagePath = storagePath;
57+
this.labels = labels;
58+
this.note = note;
59+
this.uploadedAt = uploadedAt;
60+
}
61+
62+
// Getters/setters
63+
public UUID getId() {
64+
return id;
65+
}
66+
67+
public void setId(UUID id) {
68+
this.id = id;
69+
}
70+
71+
public UUID getUserId() {
72+
return userId;
73+
}
74+
75+
public void setUserId(UUID userId) {
76+
this.userId = userId;
77+
}
78+
79+
public String getFilename() {
80+
return filename;
81+
}
82+
83+
public void setFilename(String filename) {
84+
this.filename = filename;
85+
}
86+
87+
public String getStoragePath() {
88+
return storagePath;
89+
}
90+
91+
public void setStoragePath(String storagePath) {
92+
this.storagePath = storagePath;
93+
}
94+
95+
public String[] getLabels() {
96+
return labels;
97+
}
98+
99+
public void setLabels(String[] labels) {
100+
this.labels = labels;
101+
}
102+
103+
public String getNote() {
104+
return note;
105+
}
106+
107+
public void setNote(String note) {
108+
this.note = note;
109+
}
110+
111+
public Instant getUploadedAt() {
112+
return uploadedAt;
113+
}
114+
115+
public void setUploadedAt(Instant uploadedAt) {
116+
this.uploadedAt = uploadedAt;
117+
}
118+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package dev.coms4156.project.metadetect.repository;
2+
3+
import dev.coms4156.project.metadetect.model.Image;
4+
import java.util.List;
5+
import java.util.Optional;
6+
import java.util.UUID;
7+
import org.springframework.data.repository.CrudRepository;
8+
import org.springframework.stereotype.Repository;
9+
10+
/**
11+
* Repository for accessing and querying {@link Image} entities.
12+
* Provides user-scoped lookup operations to ensure ownership checks
13+
* can be enforced at the service layer.
14+
*/
15+
@Repository
16+
public interface ImageRepository extends CrudRepository<Image, UUID> {
17+
Optional<Image> findByIdAndUserId(UUID id, UUID userId);
18+
19+
List<Image> findAllByUserIdOrderByUploadedAtDesc(UUID userId);
20+
}

0 commit comments

Comments
 (0)