Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.teamEWSN.gitdeun.common.converter;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import java.io.IOException;
import java.time.*;
import java.time.format.DateTimeParseException;

public class IsoToLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String s = p.getText();
if (s == null || s.isBlank()) return null;

// 1) 오프셋/Z 포함 → UTC LDT로
try {
return OffsetDateTime.parse(s).atZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
} catch (DateTimeParseException ignored) {}

// 2) Instant 순수 파싱 시도
try {
return Instant.parse(s).atZone(ZoneOffset.UTC).toLocalDateTime();
} catch (DateTimeParseException ignored) {}

// 3) 오프셋 없는 LocalDateTime 포맷(레거시) 방어
return LocalDateTime.parse(s);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.teamEWSN.gitdeun.common.fastapi;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.teamEWSN.gitdeun.common.converter.IsoToLocalDateTimeDeserializer;
import com.teamEWSN.gitdeun.common.fastapi.dto.AnalysisResultDto;
import com.teamEWSN.gitdeun.common.fastapi.dto.MindmapGraphDto;
import lombok.Getter;
Expand Down Expand Up @@ -42,6 +45,8 @@ public AnalysisResultDto analyzeResult(String repoUrl, String prompt, String aut
log.info("Fetch 완료 - 파일: {}, 파싱: {}",
fetchResult.getFiles_saved(), fetchResult.getFiles_parsed());

saveRepoInfo(mapId, authorizationHeader);

// Step 2: 마인드맵 기본 분석 (AI)
AnalyzeResponse analyzeResult = analyzeAI(repoUrl, prompt, authorizationHeader);
log.info("AI 분석 완료 - 디렉터리: {}", analyzeResult.getDirs_analyzed());
Expand All @@ -55,7 +60,7 @@ public AnalysisResultDto analyzeResult(String repoUrl, String prompt, String aut
RepoInfoResponse repoInfo = getRepoInfo(mapId, authorizationHeader);

// 모든 데이터를 종합하여 DTO 생성
return buildAnalysisResultDto(mapId, fetchResult, analyzeResult, graphData, repoInfo);
return buildAnalysisResultDto(mapId, analyzeResult, graphData, repoInfo);

} catch (Exception e) {
log.error("저장소 분석 실패: {}", e.getMessage(), e);
Expand Down Expand Up @@ -96,7 +101,7 @@ public AnalysisResultDto refreshMindmap(String repoUrl, String prompt, String au
}

// 저장소 파일 fetch
private FetchResponse fetchRepoInfo(String repoUrl, String authHeader) {
public FetchResponse fetchRepoInfo(String repoUrl, String authHeader) {
Map<String, String> request = new HashMap<>();
request.put("repo_url", repoUrl);

Expand Down Expand Up @@ -124,14 +129,23 @@ public void saveRepoInfo(String repoUrl, String authHeader) {
.block();
}

// 저장소 정보 조회 (TODO: FastAPI에 구현 필요)
private RepoInfoResponse getRepoInfo(String mapId, String authHeader) {
// TODO: FastAPI에 /repo/{mapId}/info 엔드포인트 구현 필요
// 현재는 기본값 반환
RepoInfoResponse info = new RepoInfoResponse();
info.setDefault_branch("main");
info.setLast_updated_at(LocalDateTime.now());
return info;
// 저장소 정보 조회
public RepoInfoResponse getRepoInfo(String mapId, String authHeader) {
try {
return webClient.get()
.uri("/repo/{mapId}/info", mapId)
.header("Authorization", authHeader)
.retrieve()
.bodyToMono(RepoInfoResponse.class)
.block();
} catch (Exception e) {
log.warn("저장소 정보 조회 실패: {}, 기본값 사용", e.getMessage());
// 조회 실패 시 기본값 반환
RepoInfoResponse info = new RepoInfoResponse();
info.setDefaultBranch("main");
info.setLastCommit(LocalDateTime.now());
return info;
}
}

/**
Expand All @@ -158,7 +172,7 @@ public AnalyzeResponse analyzeAI(String repoUrl, String prompt, String authHeade
/**
* ArangoDB에서 마인드맵 그래프 데이터를 조회
*/
private MindmapGraphDto getGraph(String mapId, String authHeader) {
public MindmapGraphDto getGraph(String mapId, String authHeader) {
return webClient.get()
.uri("/mindmap/{mapId}/graph", mapId)
.header("Authorization", authHeader)
Expand All @@ -168,7 +182,7 @@ private MindmapGraphDto getGraph(String mapId, String authHeader) {
}

// 최신 변경사항 새로고침
private RefreshResponse refreshLatest(String mapId, String prompt, String authHeader) {
public RefreshResponse refreshLatest(String mapId, String prompt, String authHeader) {
Map<String, Object> request = new HashMap<>();
if (StringUtils.hasText(prompt)) {
request.put("prompt", prompt);
Expand Down Expand Up @@ -212,7 +226,6 @@ private String extractMapId(String repoUrl) {

private AnalysisResultDto buildAnalysisResultDto(
String mapId,
FetchResponse fetchResult,
AnalyzeResponse analyzeResult,
MindmapGraphDto graphData,
RepoInfoResponse repoInfo
Expand All @@ -221,13 +234,13 @@ private AnalysisResultDto buildAnalysisResultDto(
String mapDataJson = convertGraphToJson(graphData);

// AI가 생성한 제목 또는 기본 제목
// TODO: 제목 생성 fastapi 메서드 필요
String title = String.format("%s 프로젝트 구조 분석 (디렉터리 %d개)",
mapId, analyzeResult.getDirs_analyzed());

return AnalysisResultDto.builder()
.defaultBranch(repoInfo.getDefault_branch())
.githubLastUpdatedAt(repoInfo.getLast_updated_at())
.mapData(mapDataJson)
.defaultBranch(repoInfo.getDefaultBranch())
.lastCommit(repoInfo.getLastCommit())
.title(title)
.errorMessage(null)
.build();
Expand All @@ -240,13 +253,14 @@ private AnalysisResultDto buildRefreshResultDto(
RepoInfoResponse repoInfo
) {
String mapDataJson = convertGraphToJson(graphData);

// TODO: 제목 생성 fastapi 메서드 필요
String title = String.format("%s (변경 파일 %d개 반영)",
mapId, refreshResult.getChanged_files());

return AnalysisResultDto.builder()
.defaultBranch(repoInfo.getDefault_branch())
.githubLastUpdatedAt(repoInfo.getLast_updated_at())
.mapData(mapDataJson)
.defaultBranch(repoInfo.getDefaultBranch())
.lastCommit(repoInfo.getLastCommit())
.title(title)
.errorMessage(null)
.build();
Expand Down Expand Up @@ -295,8 +309,14 @@ public static class RefreshResponse {
@Getter
@Setter
public static class RepoInfoResponse {
private String default_branch;
private LocalDateTime last_updated_at;
@JsonProperty("default_branch")
private String defaultBranch;

@JsonProperty("last_commit")
@JsonDeserialize(using = IsoToLocalDateTimeDeserializer.class)
private LocalDateTime lastCommit;


}

@Getter
Expand All @@ -308,4 +328,6 @@ public static class DeleteResponse {
private Integer nodes_removed;
private Integer recs_removed;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
public class AnalysisResultDto {
// Repo 관련 정보
private String defaultBranch;
private LocalDateTime githubLastUpdatedAt;
private LocalDateTime lastCommit;

// Mindmap 관련 정보
private String mapData; // JSON 형태의 마인드맵 데이터
private String title; // 프롬프트 및 mindmap 정보 요약
private String errorMessage; // 실패 시 전달될 에러메세지
// TODO: FastAPI 응답에 맞춰 필드 정의
Expand Down
20 changes: 18 additions & 2 deletions src/main/java/com/teamEWSN/gitdeun/common/fastapi/dto/EdgeDto.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
package com.teamEWSN.gitdeun.common.fastapi.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;

@Getter
public class EdgeDto {
private String from;
private String to;
@JsonProperty("from")
private String fromKey;

@JsonProperty("to")
private String toKey;

@JsonProperty("edge_type")
private String edgeType;

// 편의 메서드
public boolean isContainmentEdge() {
return "contains".equals(edgeType) || edgeType == null;
}

public boolean isSuggestionEdge() {
return "suggestion".equals(edgeType);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.teamEWSN.gitdeun.common.fastapi.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import java.util.List;

@Getter
public class MindmapGraphDto {
private int count;
@JsonProperty("map_id")
private String mapId;
private Integer count;
private List<NodeDto> nodes;
private List<EdgeDto> edges;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
package com.teamEWSN.gitdeun.common.fastapi.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import java.util.List;

@Getter
public class NodeDto {
private String key;

private String label;
private List<String> related_files;

@JsonProperty("related_files")
private List<String> relatedFiles;

@JsonProperty("node_type")
private String nodeType;

private String mode;

// 편의 메서드
public boolean isFileNode() {
return "file".equals(nodeType);
}

public boolean isSuggestionNode() {
return "suggestion".equals(nodeType);
}

public int getFileCount() {
return relatedFiles != null ? relatedFiles.size() : 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
@RequiredArgsConstructor
public enum CacheType {
SERVICE_AUTOCOMPLETE("serviceAutocomplete", 2, 1200), // 자동완성 캐시
USER_SKILLS("userSkills", 1, 500); // 사용자 개발기술 캐시
USER_SKILLS("userSkills", 1, 500), // 사용자 개발기술 캐시
MINDMAP_GRAPH_L1("mindmapGraphL1", 100, 1), // 30분, 최대 100개
VISIT_HISTORY_SUMMARY("visitHistorySummary", 1000, 1); // 1시간, 최대 1000개

private final String cacheName;
private final int expiredAfterWrite; // 시간(hour) 단위
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
public class WebhookUpdateDto {
// FastAPI 콜백 페이로드와 동일
private String repoUrl;
private String mapData;
private String defaultBranch;
private LocalDateTime githubLastUpdatedAt;
private LocalDateTime lastCommit;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ public class MindmapDetailResponseDto {
private Long mindmapId;
private String title;
private String branch;
private String mapData; // 핵심 데이터인 마인드맵 JSON

// 맵 데이터
private MindmapGraphResponseDto mindmapGraph;

private LocalDateTime createdAt;
private LocalDateTime updatedAt;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.teamEWSN.gitdeun.mindmap.dto;

import com.teamEWSN.gitdeun.common.fastapi.dto.EdgeDto;
import com.teamEWSN.gitdeun.common.fastapi.dto.NodeDto;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
@Builder
public class MindmapGraphResponseDto {
private Boolean success;
private String error;

// FastAPI 응답 데이터 그대로 전달
private String graphMapId;
private Integer nodeCount;
private List<NodeDto> nodes;
private List<EdgeDto> edges;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.teamEWSN.gitdeun.mindmap.dto.prompt;

import com.teamEWSN.gitdeun.mindmap.dto.MindmapGraphResponseDto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -13,7 +14,10 @@ public class PromptPreviewResponseDto {
private Long historyId;
private String prompt;
private String title;
private String previewMapData; // 미리보기용 맵 데이터

// TODO: 프롬프트 미리보기용 맵 데이터
private MindmapGraphResponseDto mindmapGraph;

private LocalDateTime createdAt;
private Boolean applied; // 현재 적용 상태
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ public class Mindmap extends AuditedEntity {
@Column(length = 50, nullable = false)
private String title;

@JdbcTypeCode(SqlTypes.JSON)
/*@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "map_data", columnDefinition = "json", nullable = false)
private String mapData;
private String mapData;*/

// TODO: 멤버수 제한 기능 (유료?)
@Builder.Default
Expand All @@ -66,10 +66,6 @@ public class Mindmap extends AuditedEntity {
private List<PromptHistory> promptHistories = new ArrayList<>();


public void updateMapData(String newMapData) {
this.mapData = newMapData;
}

public void updateTitle(String newTitle) {
this.title = newTitle;
}
Expand Down Expand Up @@ -97,7 +93,6 @@ public void applyPromptHistory(PromptHistory promptHistory) {

// 새 프롬프트 적용
promptHistory.applyToMindmap();
this.mapData = promptHistory.getMapData();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ public class PromptHistory extends CreatedEntity {
@Column(length = 50)
private String title; // 분석 결과 요약 (기록 제목)

@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "map_data", columnDefinition = "json", nullable = false)
private String mapData; // 해당 프롬프트의 분석 결과 데이터

@Builder.Default
@Column(name = "applied", nullable = false)
private Boolean applied = false; // 적용 확정 여부
Expand Down
Loading