dev #8
@@ -16,6 +16,7 @@ import java.util.logging.Logger;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ProfileManager {
|
public class ProfileManager {
|
||||||
@@ -56,22 +57,38 @@ public class ProfileManager {
|
|||||||
if (profilePath == null) {
|
if (profilePath == null) {
|
||||||
throw new IOException("Profile not found: " + profileName);
|
throw new IOException("Profile not found: " + profileName);
|
||||||
}
|
}
|
||||||
|
logger.info("Resolved " + type + " profile '" + profileName + "' -> " + profilePath);
|
||||||
return resolveInheritance(profilePath);
|
return resolveInheritance(profilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path findProfileFile(String name, String type) {
|
private Path findProfileFile(String name, String type) {
|
||||||
// Check aliases first
|
// Check aliases first
|
||||||
String resolvedName = profileAliases.getOrDefault(name, name);
|
String resolvedName = profileAliases.getOrDefault(name, name);
|
||||||
|
|
||||||
// Simple search: look for name.json in the profiles_root recursively
|
// Look for name.json under the expected type directory first to avoid
|
||||||
// Type could be "machine", "process", "filament" to narrow down, but for now global search
|
// collisions across vendors/profile families with same filename.
|
||||||
String filename = resolvedName.endsWith(".json") ? resolvedName : resolvedName + ".json";
|
String filename = toJsonFilename(resolvedName);
|
||||||
|
|
||||||
try (Stream<Path> stream = Files.walk(Paths.get(profilesRoot))) {
|
try (Stream<Path> stream = Files.walk(Paths.get(profilesRoot))) {
|
||||||
Optional<Path> found = stream
|
List<Path> candidates = stream
|
||||||
.filter(p -> p.getFileName().toString().equals(filename))
|
.filter(p -> p.getFileName().toString().equals(filename))
|
||||||
.findFirst();
|
.sorted()
|
||||||
return found.orElse(null);
|
.toList();
|
||||||
|
|
||||||
|
if (candidates.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type != null && !type.isBlank() && !"any".equalsIgnoreCase(type)) {
|
||||||
|
Optional<Path> typed = candidates.stream()
|
||||||
|
.filter(p -> pathContainsSegment(p, type))
|
||||||
|
.findFirst();
|
||||||
|
if (typed.isPresent()) {
|
||||||
|
return typed.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return candidates.get(0);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.severe("Error searching for profile: " + e.getMessage());
|
logger.severe("Error searching for profile: " + e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
@@ -85,14 +102,20 @@ public class ProfileManager {
|
|||||||
// 2. Check inherits
|
// 2. Check inherits
|
||||||
if (currentNode.has("inherits")) {
|
if (currentNode.has("inherits")) {
|
||||||
String parentName = currentNode.get("inherits").asText();
|
String parentName = currentNode.get("inherits").asText();
|
||||||
// Try to find parent in same directory or standard search
|
// Try local directory first with explicit .json filename.
|
||||||
Path parentPath = currentPath.getParent().resolve(parentName);
|
String parentFilename = toJsonFilename(parentName);
|
||||||
|
Path parentPath = currentPath.getParent().resolve(parentFilename);
|
||||||
if (!Files.exists(parentPath)) {
|
if (!Files.exists(parentPath)) {
|
||||||
// If not in same dir, search globally
|
// Fallback to the same profile type directory before global.
|
||||||
|
String inferredType = inferTypeFromPath(currentPath);
|
||||||
|
parentPath = findProfileFile(parentName, inferredType);
|
||||||
|
}
|
||||||
|
if (parentPath == null || !Files.exists(parentPath)) {
|
||||||
parentPath = findProfileFile(parentName, "any");
|
parentPath = findProfileFile(parentName, "any");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentPath != null && Files.exists(parentPath)) {
|
if (parentPath != null && Files.exists(parentPath)) {
|
||||||
|
logger.info("Resolved inherits '" + parentName + "' for " + currentPath + " -> " + parentPath);
|
||||||
// Recursive call
|
// Recursive call
|
||||||
ObjectNode parentNode = resolveInheritance(parentPath);
|
ObjectNode parentNode = resolveInheritance(parentPath);
|
||||||
// Merge current into parent (child overrides parent)
|
// Merge current into parent (child overrides parent)
|
||||||
@@ -123,4 +146,30 @@ public class ProfileManager {
|
|||||||
mainNode.set(fieldName, jsonNode);
|
mainNode.set(fieldName, jsonNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String toJsonFilename(String name) {
|
||||||
|
return name.endsWith(".json") ? name : name + ".json";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean pathContainsSegment(Path path, String segment) {
|
||||||
|
String normalized = path.toString().replace('\\', '/');
|
||||||
|
String needle = "/" + segment + "/";
|
||||||
|
return normalized.contains(needle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String inferTypeFromPath(Path path) {
|
||||||
|
if (path == null) {
|
||||||
|
return "any";
|
||||||
|
}
|
||||||
|
if (pathContainsSegment(path, "machine")) {
|
||||||
|
return "machine";
|
||||||
|
}
|
||||||
|
if (pathContainsSegment(path, "process")) {
|
||||||
|
return "process";
|
||||||
|
}
|
||||||
|
if (pathContainsSegment(path, "filament")) {
|
||||||
|
return "filament";
|
||||||
|
}
|
||||||
|
return "any";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ public class SlicerService {
|
|||||||
ObjectNode filamentProfile = profileManager.getMergedProfile(filamentName, "filament");
|
ObjectNode filamentProfile = profileManager.getMergedProfile(filamentName, "filament");
|
||||||
ObjectNode processProfile = profileManager.getMergedProfile(processName, "process");
|
ObjectNode processProfile = profileManager.getMergedProfile(processName, "process");
|
||||||
|
|
||||||
|
logger.info("Slicer profiles: machine='" + machineName + "', filament='" + filamentName + "', process='" + processName + "'");
|
||||||
|
logger.info("Machine limits: printable_area=" + machineProfile.path("printable_area")
|
||||||
|
+ ", printable_height=" + machineProfile.path("printable_height")
|
||||||
|
+ ", bed_exclude_area=" + machineProfile.path("bed_exclude_area")
|
||||||
|
+ ", head_wrap_detect_zone=" + machineProfile.path("head_wrap_detect_zone"));
|
||||||
|
|
||||||
// Apply Overrides
|
// Apply Overrides
|
||||||
if (machineOverrides != null) {
|
if (machineOverrides != null) {
|
||||||
machineOverrides.forEach(machineProfile::put);
|
machineOverrides.forEach(machineProfile::put);
|
||||||
|
|||||||
Reference in New Issue
Block a user