diff --git a/migration-examples/layout/index.html b/migration-examples/layout/index.html
index 3af7fc91..00ca1c2f 100644
--- a/migration-examples/layout/index.html
+++ b/migration-examples/layout/index.html
@@ -421,6 +421,7 @@
+
@@ -449,6 +450,7 @@
* @typedef {Object} LayoutData
* @property {PageEntry[]} pages
* @property {TemplateEntry[]} templates
+ * @property {({pageIndex: number, areaIndex: number}|null)[]} [rowMap]
*/
/**
@@ -704,7 +706,7 @@
*/
function parseCsvToLayoutData(text) {
const lines = text.split(/\r?\n/);
- if (!lines.length) return { pages: [], templates: [] };
+ if (!lines.length) return { pages: [], templates: [], rowMap: [] };
// Parse headers, stripping the " (read-only)" suffix added by Mapping.displayHeader
const headers = parseCsvLine(lines[0]).map(h => {
@@ -715,12 +717,13 @@
/** @param {string[]} row @param {string} name @returns {string} */
const col = (row, name) => { const idx = headers.indexOf(name); return idx >= 0 ? (row[idx] ?? '') : ''; };
- // Group rows into pages; each unique page in the CSV keeps its declaration order
- /** @type {Map} */
+ /** @type {Map} */
const pageMap = new Map();
for (let i = 1; i < lines.length; i++) {
if (!lines[i].trim()) continue;
const row = parseCsvLine(lines[i]);
+ if (col(row, 'type').trim().toLowerCase() === 'base') continue;
+
const pageId = col(row, 'pageId') || null;
const templateId = col(row, 'templateId') || null;
const pageKey = pageId && templateId
@@ -741,12 +744,13 @@
pageHeight: col(row, 'pageHeight'),
},
rows: [],
+ lineIndices: [],
});
}
pageMap.get(pageKey).rows.push(row);
+ pageMap.get(pageKey).lineIndices.push(i);
}
- // Assign templatePageIndex as the ordinal of each real page within its template (CSV order)
/** @type {Map} */
const pageIndexMap = new Map();
/** @type {Map} */
@@ -758,29 +762,38 @@
tmplPageCounter.set(meta.templateId, n + 1);
}
- // Build PageEntry objects
+ // TODO d.svitak - review start
/** @type {PageEntry[]} */
const pages = [];
- for (const [pageKey, { meta, rows }] of pageMap) {
- const rawAreas = /** @type {{x:number,y:number,w:number,h:number,flowToNextPage:boolean,interactiveFlowName:string,contentPreview:string}[]} */ (
- rows.map(row => {
- const x = parseSizeMm(col(row, 'x'));
- const y = parseSizeMm(col(row, 'y'));
- const w = parseSizeMm(col(row, 'width'));
- const h = parseSizeMm(col(row, 'height'));
- if (x == null || y == null || w == null || h == null) return null;
- return {
+ /** @type {({pageIndex: number, areaIndex: number}|null)[]} */
+ const rowMap = new Array(lines.length).fill(null);
+ for (const [pageKey, { meta, rows, lineIndices }] of pageMap) {
+ const rawAreasWithLine = rows.map((row, idx) => {
+ const x = parseSizeMm(col(row, 'x'));
+ const y = parseSizeMm(col(row, 'y'));
+ const w = parseSizeMm(col(row, 'width'));
+ const h = parseSizeMm(col(row, 'height'));
+ if (x == null || y == null || w == null || h == null) return null;
+ return {
+ area: {
x, y, w, h,
flowToNextPage: col(row, 'flowToNextPage') === 'true',
interactiveFlowName: col(row, 'interactiveFlowName') || '',
contentPreview: col(row, 'contentPreview') || '',
- };
- }).filter(a => a != null)
+ },
+ lineIndex: lineIndices[idx],
+ };
+ }).filter(a => a != null);
+ const rawAreas = /** @type {{x:number,y:number,w:number,h:number,flowToNextPage:boolean,interactiveFlowName:string,contentPreview:string}[]} */ (
+ rawAreasWithLine.map(a => a.area)
);
const containment = computeContainment(rawAreas);
const areas = /** @type {AreaEntry[]} */ (rawAreas.map((a, idx) => ({ ...a, containedIn: containment[idx] })));
+ const pageIndex = pages.length;
+ rawAreasWithLine.forEach((a, areaIndex) => { rowMap[a.lineIndex] = { pageIndex, areaIndex }; });
+
const pw = parseSizeMm(meta.pageWidth);
const ph = parseSizeMm(meta.pageHeight);
pages.push(/** @type {PageEntry} */ ({
@@ -794,16 +807,43 @@
}));
}
- return { pages, templates: deriveTemplates(pages) };
+ return { pages, templates: deriveTemplates(pages), rowMap };
}
+// Raw CSV state kept alongside the parsed LayoutData so the file can be re-serialized
+// losslessly (including columns/rows the viewer doesn't otherwise use) for saving back to disk.
+/** @type {string[]|null} */
+let currentCsvHeaders = null;
+/** @type {string[][]|null} */
+let currentCsvRows = null;
+let currentFileName = "areas.csv";
+/** @type {({pageIndex: number, areaIndex: number}|null)[]} */
+let currentRowMap = [];
+
+const saveCsvBtn = /** @type {HTMLButtonElement} */ (document.getElementById("save-csv"));
+
/**
* @param {File} file
*/
async function loadFile(file) {
try {
statusEl.textContent = "";
- render(parseCsvToLayoutData(await file.text()));
+ const text = await file.text();
+
+ const lines = text.split(/\r?\n/);
+ if (lines.length && lines[0].trim() !== "") {
+ currentCsvHeaders = parseCsvLine(lines[0]);
+ currentCsvRows = lines.slice(1).map(parseCsvLine);
+ } else {
+ currentCsvHeaders = null;
+ currentCsvRows = null;
+ }
+ currentFileName = file.name || "areas.csv";
+ saveCsvBtn.disabled = !currentCsvHeaders;
+
+ const layoutData = parseCsvToLayoutData(text);
+ currentRowMap = layoutData.rowMap ?? [];
+ render(layoutData);
} catch (err) {
statusEl.textContent = "Error: " + /** @type {Error} */ (err).message;
}
@@ -814,6 +854,181 @@
if (file) loadFile(file);
});
+function normalizeHeaderName(header) {
+ const s = (header ?? "").trim();
+ return s.endsWith(" (read-only)") ? s.slice(0, -" (read-only)".length) : s;
+}
+
+function ensureCsvColumn(headers, rows, logicalName) {
+ const idx = headers.findIndex(h => normalizeHeaderName(h) === logicalName);
+ if (idx >= 0) return idx;
+ const insertIdx = headers.findIndex(h => normalizeHeaderName(h) === "contentPreview");
+ const at = insertIdx >= 0 ? insertIdx : headers.length;
+ headers.splice(at, 0, logicalName);
+ rows.forEach(row => { row.splice(at, 0, ""); });
+ return at;
+}
+
+function csvEscapeField(field) {
+ const s = field ?? "";
+ if (/[",\r\n]/.test(s)) {
+ return '"' + s.replace(/"/g, '""') + '"';
+ }
+ return s;
+}
+
+function serializeCsv(headers, rows) {
+ const lines = [headers.map(csvEscapeField).join(",")];
+ for (const row of rows) {
+ lines.push(row.map(csvEscapeField).join(","));
+ }
+ return lines.join("\r\n") + "\r\n";
+}
+
+function computeBaseTemplateData(data, viewModel, analysis) {
+ /** @type {string[][]} */
+ const baseRows = [];
+ /** @type {Map} */
+ const overridesByPageIndex = new Map();
+
+ viewModel.templateGroups.forEach((templateGroup, templateGroupIndex) => {
+ const baseTemplateId = `G${templateGroupIndex + 1}`;
+ const baseTemplateName = `Base template of ${templateGroup.templateNames.join(" / ")}`;
+
+ templateGroup.pageGroups.forEach((pageGroup, pageGroupIndex) => {
+ const basePageId = `${baseTemplateId}-P${pageGroupIndex + 1}`;
+ const basePageName = `Page group ${pageGroupIndex + 1}`;
+
+ const representativePageIndex = pageGroup.pageIndices[0];
+ const representativePage = data.pages[representativePageIndex];
+ const representativeGroups = analysis.pageProximityGroups[representativePageIndex] ?? [];
+ const pageWidthMm = representativePage.pageSize ? `${representativePage.pageSize.w}mm` : "";
+ const pageHeightMm = representativePage.pageSize ? `${representativePage.pageSize.h}mm` : "";
+
+ representativeGroups.forEach((pg, areaGroupIndex) => {
+ const flowName = `${basePageId}.Area${areaGroupIndex + 1}`;
+ const flowToNextPage = pg.areaIndices.some(ai => representativePage.areas[ai]?.flowToNextPage);
+ const contentPreview = pg.areaIndices
+ .map(ai => representativePage.areas[ai]?.contentPreview)
+ .filter(Boolean)
+ .join(";");
+ baseRows.push([
+ baseTemplateId, baseTemplateName, basePageId, basePageName,
+ pageWidthMm, pageHeightMm,
+ flowName, String(flowToNextPage),
+ `${pg.position.x}mm`, `${pg.position.y}mm`, `${pg.position.w}mm`, `${pg.position.h}mm`,
+ "Base", "", contentPreview,
+ ]);
+ });
+
+ pageGroup.pageIndices.forEach(pageIndex => {
+ const page = data.pages[pageIndex];
+ const ownGroups = pageIndex === representativePageIndex
+ ? representativeGroups
+ : (analysis.pageProximityGroups[pageIndex] ?? []);
+
+ /** @type {(string|null)[]} */
+ const flowNames = new Array(page.areas.length).fill(null);
+ ownGroups.forEach((pg, ordinal) => {
+ if (ordinal >= representativeGroups.length) return;
+ const flowName = `${basePageId}.Area${ordinal + 1}`;
+ pg.areaIndices.forEach(ai => { flowNames[ai] = flowName; });
+ });
+ overridesByPageIndex.set(pageIndex, { flowNames, targetId: `$${baseTemplateId}` });
+ });
+ });
+ });
+
+ return { baseRows, overridesByPageIndex };
+}
+
+async function saveCsv() {
+ if (!currentCsvHeaders || !currentCsvRows) {
+ statusEl.textContent = "No CSV loaded to save.";
+ return;
+ }
+ if (!currentData || !currentViewModel || !currentAnalysis) {
+ statusEl.textContent = "No layout data loaded to save.";
+ return;
+ }
+
+ const headers = [...currentCsvHeaders];
+ const rows = currentCsvRows.map(row => [...row]);
+
+ const typeIdx = ensureCsvColumn(headers, rows, "type");
+ const targetIdIdx = ensureCsvColumn(headers, rows, "targetId");
+ const flowNameIdx = ensureCsvColumn(headers, rows, "interactiveFlowName");
+
+ const { baseRows, overridesByPageIndex } = computeBaseTemplateData(currentData, currentViewModel, currentAnalysis);
+
+ currentRowMap.forEach((entry, lineIndex) => {
+ if (!entry) return;
+ const rowIdx = lineIndex - 1;
+ const row = rows[rowIdx];
+ if (!row) return;
+
+ const override = overridesByPageIndex.get(entry.pageIndex);
+ if (!override) return;
+
+ row[targetIdIdx] = override.targetId;
+ const flowName = override.flowNames[entry.areaIndex];
+ if (flowName != null) row[flowNameIdx] = flowName;
+ });
+
+ for (let i = rows.length - 1; i >= 0; i--) {
+ if (rows[i].every(cell => cell === "")) {
+ rows.splice(i, 1);
+ } else if (!rows[i][typeIdx]) {
+ rows[i][typeIdx] = "Standard";
+ }
+ }
+
+ baseRows.forEach(baseRow => {
+ const byLogicalName = {
+ templateId: baseRow[0], templateName: baseRow[1], pageId: baseRow[2], pageName: baseRow[3],
+ pageWidth: baseRow[4], pageHeight: baseRow[5], interactiveFlowName: baseRow[6], flowToNextPage: baseRow[7],
+ x: baseRow[8], y: baseRow[9], width: baseRow[10], height: baseRow[11],
+ type: baseRow[12], targetId: baseRow[13], contentPreview: baseRow[14],
+ };
+ const row = headers.map(h => byLogicalName[normalizeHeaderName(h)] ?? "");
+ rows.push(row);
+ });
+
+ const text = serializeCsv(headers, rows);
+
+ if (typeof window.showSaveFilePicker === "function") {
+ try {
+ const handle = await window.showSaveFilePicker({
+ suggestedName: currentFileName,
+ types: [{ description: "CSV file", accept: { "text/csv": [".csv"] } }],
+ });
+ const writable = await handle.createWritable();
+ await writable.write(text);
+ await writable.close();
+ statusEl.textContent = `Saved ${handle.name}`;
+ return;
+ } catch (err) {
+ if (/** @type {Error} */ (err).name === "AbortError") return;
+ statusEl.textContent = "Error saving file: " + /** @type {Error} */ (err).message;
+ return;
+ }
+ }
+
+ const blob = new Blob([text], { type: "text/csv" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = currentFileName;
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ URL.revokeObjectURL(url);
+ statusEl.textContent = `Downloaded ${currentFileName}`;
+}
+
+saveCsvBtn.addEventListener("click", () => { saveCsv(); });
+// TODO d.svitak - review end
+
document.body.addEventListener("dragover", e => e.preventDefault());
document.body.addEventListener("drop", e => {
e.preventDefault();
@@ -1979,8 +2194,8 @@
*/
function areaLabel(preview) {
if (!preview) return "";
- const m = preview.match(/\(([^)]+)\)$/);
- return m ? m[1] : preview.slice(0, 40);
+ const firstChunk = preview.split(";")[0];
+ return firstChunk.slice(0, 40);
}
/**
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasExport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasExport.groovy
index 00063705..722444da 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasExport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasExport.groovy
@@ -50,7 +50,9 @@ static void run(Migration migration, Path path) {
Mapping.displayHeader("y", true),
Mapping.displayHeader("width", true),
Mapping.displayHeader("height", true),
- Mapping.displayHeader("contentPreview", true)
+ Mapping.displayHeader("type", false),
+ Mapping.displayHeader("targetId", false),
+ Mapping.displayHeader("contentPreview", true),
]
writer.writeLine(headers.join(","))
templates.each { template ->
@@ -102,6 +104,9 @@ static String buildArea(Migration migration, Number idx, Area area, DocumentObje
builder.append(Csv.serialize(area.position.width) + ",")
builder.append(Csv.serialize(area.position.height) + ",")
+ builder.append("Standard,")
+ builder.append(Csv.serialize(page?.baseTemplate ?: template?.baseTemplate) + ",")
+
builder.append(Csv.serialize(migration.previewProvider.buildDocumentContentListPreview(area.content)))
return builder.toString()
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasImport.groovy
index 0da1cbd4..ce43785b 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AreasImport.groovy
@@ -7,10 +7,17 @@
package com.quadient.migration.example.common.mapping
import com.quadient.migration.api.Migration
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplate
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
+import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.example.common.util.Csv
import com.quadient.migration.example.common.util.Mapping
+import com.quadient.migration.shared.BaseTemplateArea
+import com.quadient.migration.shared.BaseTemplatePage
+import com.quadient.migration.shared.Position
+import com.quadient.migration.shared.Size
import groovy.transform.Field
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@@ -30,20 +37,29 @@ static void run(Migration migration, Path path) {
def fileLines = path.toFile().readLines()
def columnNames = Csv.parseColumnNames(fileLines.removeFirst()).collect { Mapping.normalizeHeader(it) }
- def mappings = new HashMap()
+ def areaMappings = new HashMap()
+ def docObjectsToTargetIds = new LinkedHashMap()
+ def baseTemplateDrafts = new LinkedHashMap()
+
DocumentObject currentDocumentObject = null
- MappingItem.Area mapping = null
+ MappingItem.Area areaMapping = null
int areaIndex = 0
for (line in fileLines) {
def values = Csv.getCells(line, columnNames)
+ def type = Csv.deserialize(values.get("type"), String.class) ?: "Standard"
+ if (type.equalsIgnoreCase("Base")) {
+ assignAreaToBaseTemplateDraft(baseTemplateDrafts, values)
+ continue
+ }
+
def pageId = Csv.deserialize(values.get("pageId"), String.class)
def templateId = Csv.deserialize(values.get("templateId"), String.class)
def documentObjectId = pageId ?: templateId
if (currentDocumentObject?.id != documentObjectId) {
if (currentDocumentObject != null) {
- mappings[currentDocumentObject.id] = mapping
+ areaMappings[currentDocumentObject.id] = areaMapping
}
def documentObjectModel = migration.documentObjectRepository.find(documentObjectId)
@@ -51,29 +67,119 @@ static void run(Migration migration, Path path) {
throw new IllegalStateException("Document object '${documentObjectId}' not found.")
}
- mapping = migration.mappingRepository.getAreaMapping(documentObjectId)
+ areaMapping = migration.mappingRepository.getAreaMapping(documentObjectId)
currentDocumentObject = documentObjectModel
areaIndex = 0
}
def interactiveFlowName = Csv.deserialize(values.get("interactiveFlowName"), String.class)
- mapping.areas[areaIndex] = interactiveFlowName
+ areaMapping.areas[areaIndex] = interactiveFlowName
def flowToNextPage = Csv.deserialize(values.get("flowToNextPage"), Boolean.class)
- mapping.flowToNextPage[areaIndex] = flowToNextPage ?: false
+ areaMapping.flowToNextPage[areaIndex] = flowToNextPage ?: false
+
+ def targetId = Csv.deserialize(values.get("targetId"), String.class)
+ if (targetId) {
+ if (pageId && !docObjectsToTargetIds.containsKey(pageId)) {
+ docObjectsToTargetIds[pageId] = targetId
+ }
+ if (templateId && !docObjectsToTargetIds.containsKey(templateId)) {
+ docObjectsToTargetIds[templateId] = targetId
+ }
+ }
areaIndex++
}
if (currentDocumentObject != null) {
- mappings[currentDocumentObject.id] = mapping
+ areaMappings[currentDocumentObject.id] = areaMapping
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, areaMappings, "area mappings", log)
migration.mappingRepository.applyAllAreaMappings()
+
+ applyDocumentObjectTargetIdMappings(migration, docObjectsToTargetIds)
+ applyBaseTemplateDraftMappings(migration, baseTemplateDrafts)
}
+private static void assignAreaToBaseTemplateDraft(Map baseTemplateDrafts, Map values) {
+ def baseTemplateId = Csv.deserialize(values.get("templateId"), String.class)
+ if (!baseTemplateId) {
+ throw new IllegalStateException("Rows of type 'Base' must specify a templateId identifying the base template.")
+ }
+ def pageGroupId = Csv.deserialize(values.get("pageId"), String.class) ?: baseTemplateId
+
+ def baseTemplateDraft = baseTemplateDrafts.computeIfAbsent(baseTemplateId) { new BaseTemplateDraft() }
+ if (baseTemplateDraft.name == null) {
+ baseTemplateDraft.name = Csv.deserialize(values.get("templateName"), String.class)
+ }
+
+ def page = baseTemplateDraft.pages.computeIfAbsent(pageGroupId) {
+ new BaseTemplatePage(Csv.deserialize(values.get("pageName"), String.class),
+ Csv.deserialize(values.get("pageWidth"), Size.class),
+ Csv.deserialize(values.get("pageHeight"), Size.class),
+ new ArrayList())
+ }
+
+ def interactiveFlowName = Csv.deserialize(values.get("interactiveFlowName"), String.class)
+ if (!interactiveFlowName) {
+ throw new IllegalStateException("Rows of type 'Base' must specify an interactiveFlowName for the consolidated area.")
+ }
+ def x = Csv.deserialize(values.get("x"), Size.class)
+ def y = Csv.deserialize(values.get("y"), Size.class)
+ def width = Csv.deserialize(values.get("width"), Size.class)
+ def height = Csv.deserialize(values.get("height"), Size.class)
+ def position = (x != null && y != null && width != null && height != null) ? new Position(x, y, width, height) : null
+ def flowToNextPage = Csv.deserialize(values.get("flowToNextPage"), Boolean.class) ?: false
+
+ page.areas.add(new BaseTemplateArea(interactiveFlowName, position, flowToNextPage))
+}
+
+private static void applyDocumentObjectTargetIdMappings(Migration migration, Map docObjectsToTargetIds) {
+ if (docObjectsToTargetIds.isEmpty()) return
+
+ def mappings = new HashMap()
+ docObjectsToTargetIds.each { documentObjectId, targetId ->
+ def mapping = migration.mappingRepository.getDocumentObjectMapping(documentObjectId)
+ def existingObject = migration.documentObjectRepository.find(documentObjectId)
+
+ if (mapping.name == null) mapping.name = existingObject?.name
+ if (mapping.internal == null) mapping.internal = existingObject?.internal
+ if (mapping.targetFolder == null) mapping.targetFolder = existingObject?.targetFolder
+ if (mapping.variableStructureRef == null) mapping.variableStructureRef = existingObject?.variableStructureRef?.id
+ if (mapping.skip == null) mapping.skip = existingObject?.skip
+
+ mapping.baseTemplate = Csv.deserialize(targetId, BaseTemplateLocation.class)
+ mappings[documentObjectId] = mapping
+ }
+
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "document object base template ref mappings", log)
+ migration.mappingRepository.applyAllDocumentObjectMappings()
+}
+
+private static void applyBaseTemplateDraftMappings(Migration migration, Map baseTemplateDrafts) {
+ if (baseTemplateDrafts.isEmpty()) return
+
+ def mappings = new HashMap()
+ baseTemplateDrafts.each { baseTemplateId, draft ->
+ def existing = migration.baseTemplateRepository.find(baseTemplateId)
+ if (existing == null) {
+ migration.baseTemplateRepository.upsert(new BaseTemplate(baseTemplateId, null, [], new CustomFieldMap(new HashMap()), null, [], null, null))
+ }
+
+ def mapping = migration.mappingRepository.getBaseTemplateMapping(baseTemplateId)
+ mapping.name = draft.name ?: existing?.name
+ mapping.targetFolder = existing?.targetFolder
+ mapping.pages = new ArrayList(draft.pages.values())
+
+ mappings[baseTemplateId] = mapping
+ }
+
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "base template mappings", log)
+ migration.mappingRepository.applyAllBaseTemplateMappings()
+}
+
+class BaseTemplateDraft {
+ String name
+ Map pages = new LinkedHashMap<>()
+}
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AttachmentsImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AttachmentsImport.groovy
index c6f95b2f..6576cfe3 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AttachmentsImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/AttachmentsImport.groovy
@@ -89,10 +89,6 @@ static void run(Migration migration, Path attachmentsFilePath) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "attachment mappings", log)
migration.mappingRepository.applyAllAttachmentMappings()
}
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DisplayRulesImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DisplayRulesImport.groovy
index 62630cf8..43f321eb 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DisplayRulesImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DisplayRulesImport.groovy
@@ -7,6 +7,7 @@
package com.quadient.migration.example.common.mapping
import com.quadient.migration.api.Migration
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.example.common.util.Csv
import com.quadient.migration.example.common.util.Mapping
@@ -56,7 +57,7 @@ static void run(Migration migration, File file) {
def newInternal = Csv.deserialize(values.get("internal"), boolean)
existingMapping.internal = newInternal
- def newBaseTemplate = Csv.deserialize(values.get("baseTemplate"), String.class)
+ def newBaseTemplate = Csv.deserialize(values.get("baseTemplate"), BaseTemplateLocation.class)
existingMapping.baseTemplate = newBaseTemplate
def newTargetFolder = Csv.deserialize(values.get("targetFolder"), String.class)
@@ -83,10 +84,6 @@ static void run(Migration migration, File file) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "display rule mappings", log)
migration.mappingRepository.applyAllDisplayRuleMappings()
}
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DocumentObjectsImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DocumentObjectsImport.groovy
index 37e016ba..3c30cd55 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DocumentObjectsImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/DocumentObjectsImport.groovy
@@ -7,6 +7,7 @@
package com.quadient.migration.example.common.mapping
import com.quadient.migration.api.Migration
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.example.common.util.Csv
import com.quadient.migration.example.common.util.Mapping
@@ -59,8 +60,8 @@ static void run(Migration migration, Path documentObjFilePath) {
def newInternal = Csv.deserialize(values.get("internal"), boolean)
Mapping.mapProp(existingMapping, existingDocObject, "internal", newInternal)
- def newBaseTemplate = Csv.deserialize(values.get("baseTemplate"), String.class)
- Mapping.mapProp(existingMapping, existingDocObject, "baseTemplate", newBaseTemplate)
+ def newBaseTemplate = Csv.deserialize(values.get("baseTemplate"), BaseTemplateLocation.class)
+ existingMapping.baseTemplate = newBaseTemplate
def newTargetFolder = Csv.deserialize(values.get("targetFolder"), String.class)
Mapping.mapProp(existingMapping, existingDocObject, "targetFolder", newTargetFolder)
@@ -93,10 +94,6 @@ static void run(Migration migration, Path documentObjFilePath) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "document object mappings", log)
migration.mappingRepository.applyAllDocumentObjectMappings()
}
\ No newline at end of file
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ImagesImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ImagesImport.groovy
index fb041b6e..5375ac27 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ImagesImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ImagesImport.groovy
@@ -92,10 +92,6 @@ static void run(Migration migration, Path imagesFilePath) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "image mappings", log)
migration.mappingRepository.applyAllImageMappings()
}
\ No newline at end of file
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ParagraphStylesImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ParagraphStylesImport.groovy
index ab34b00d..55c94395 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ParagraphStylesImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/ParagraphStylesImport.groovy
@@ -58,11 +58,7 @@ static void run(Migration migration, Path path) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "paragraph style mappings", log)
migration.mappingRepository.applyAllParagraphStyleMappings()
}
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TablesImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TablesImport.groovy
index a8e5a758..9d3fabed 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TablesImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TablesImport.groovy
@@ -83,16 +83,11 @@ static void run(Migration migration, Path path) {
tablesByDocObjId.computeIfAbsent(docObjId) { [] }.add(entry)
}
- def mappings = tablesByDocObjId.collectEntries { docObjId, tables ->
+ Map mappings = tablesByDocObjId.collectEntries { docObjId, tables ->
[docObjId, new MappingItem.Table(null, tables)]
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info("Upserting table mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)")
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
-
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "table mappings", log)
migration.mappingRepository.applyAllTableMappings { hasErrors = true }
if (hasErrors) {
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TextStylesImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TextStylesImport.groovy
index 97cc09a6..bedcd828 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TextStylesImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/TextStylesImport.groovy
@@ -56,11 +56,7 @@ static void run(Migration migration, Path path) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "text style mappings", log)
migration.mappingRepository.applyAllTextStyleMappings()
}
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/VariablesImport.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/VariablesImport.groovy
index fd9ca30e..94a9a0f4 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/VariablesImport.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/mapping/VariablesImport.groovy
@@ -10,6 +10,7 @@ package com.quadient.migration.example.common.mapping
import com.quadient.migration.api.Migration
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.api.dto.migrationmodel.VariableRef
+import com.quadient.migration.api.dto.migrationmodel.builder.VariableStructureBuilder
import com.quadient.migration.example.common.util.Csv
import com.quadient.migration.example.common.util.Mapping
import com.quadient.migration.shared.DataType
@@ -39,6 +40,11 @@ static void run(Migration migration, Path path) {
def structureId = Mapping.variableStructureIdFromFileName(path.fileName.toString(), migration.projectConfig.name)
def structureMapping = migration.mappingRepository.getVariableStructureMapping(structureId)
+ def existingStructure = migration.variableStructureRepository.find(structureId)
+ if (existingStructure == null) {
+ migration.variableStructureRepository.upsert(new VariableStructureBuilder(structureId).build())
+ }
+
def languageVariableFound = false
def mappings = new HashMap()
for (line in lines) {
@@ -74,11 +80,7 @@ static void run(Migration migration, Path path) {
}
}
- def batches = mappings.entrySet().collate(1000)
- for (int i = 0; i < batches.size(); i++) {
- log.info "Upserting mappings batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
- migration.mappingRepository.upsertBatch(batches[i].collectEntries())
- }
+ Mapping.upsertBatched(migration.mappingRepository, mappings, "variable mappings", log)
migration.mappingRepository.applyAllVariableMappings()
if (!languageVariableFound) {
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Csv.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Csv.groovy
index cd665cc3..fb138349 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Csv.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Csv.groovy
@@ -1,5 +1,8 @@
package com.quadient.migration.example.common.util
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.api.dto.migrationmodel.Tab
import com.quadient.migration.api.dto.migrationmodel.Tabs
import com.quadient.migration.shared.Color
@@ -102,6 +105,8 @@ static String serialize(Object obj, Size.Unit unitOverride) {
case Long: return obj.toString()
case Color: return obj.toHex()
case IcmPath: return obj.toString()
+ case BaseTemplateRef: return "\$${obj.id}"
+ case LiteralBaseTemplatePath: return obj.path
case Size: return unitOverride != null ? obj.toString(unitOverride) : obj.toString()
case Tabs: return """{ "tabs": ${serialize(obj.tabs)}; "useOutsideTabs": "${serialize(obj.useOutsideTabs)}" }"""
case Tab: return """{ "position": ${serialize(obj.position)}; "type": "${serialize(obj.type)}" }"""
@@ -142,6 +147,10 @@ static T deserialize(String value, Class cls) {
case IcmPath: return IcmPath.from(value) as T
case Color: return Color.fromHex(value) as T
case Size: return Size.fromString(value) as T
+ case BaseTemplateLocation: {
+ if (value.startsWith("@") || value.startsWith("\$")) return new BaseTemplateRef(value.substring(1)) as T
+ return new LiteralBaseTemplatePath(value) as T
+ }
case Boolean:
case boolean:
if (value.toLowerCase() == "true") {
diff --git a/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Mapping.groovy b/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Mapping.groovy
index 899df365..fe9921cd 100644
--- a/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Mapping.groovy
+++ b/migration-examples/src/main/groovy/com/quadient/migration/example/common/util/Mapping.groovy
@@ -1,5 +1,9 @@
package com.quadient.migration.example.common.util
+import com.quadient.migration.api.dto.migrationmodel.MappingItem
+import com.quadient.migration.api.repository.MappingRepository
+import org.slf4j.Logger
+
import java.nio.file.Path
import java.nio.file.Paths
@@ -91,3 +95,11 @@ static String normalizeHeader(String displayName) {
}
return s.trim()
}
+
+static void upsertBatched(MappingRepository mappingRepository, Map mappings, String label, Logger log) {
+ def batches = mappings.entrySet().collate(1000)
+ for (int i = 0; i < batches.size(); i++) {
+ log.info "Upserting ${label} batch ${i + 1}/${batches.size()} (${batches[i].size()} items)"
+ mappingRepository.upsertBatch(batches[i].collectEntries())
+ }
+}
diff --git a/migration-examples/src/test/groovy/AreasExportTest.groovy b/migration-examples/src/test/groovy/AreasExportTest.groovy
index 69f2d736..f589766c 100644
--- a/migration-examples/src/test/groovy/AreasExportTest.groovy
+++ b/migration-examples/src/test/groovy/AreasExportTest.groovy
@@ -46,12 +46,12 @@ class AreasExportTest {
AreasExport.run(migration, mappingFile)
def expected = """\
- templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),contentPreview (read-only)
- full tmpl,,full page,,,,test flow2,false,0mm,0mm,0mm,0mm,
- full tmpl,,full page,,,,test flow3,true,0mm,0mm,0mm,0mm,
- full tmpl,,full page,,,,,false,0mm,0mm,0mm,0mm,
- full tmpl,,full page,,,,test flow5,false,0mm,0mm,0mm,0mm,
- ,,unreferenced page,,,,test flow,true,0mm,0mm,0mm,0mm,
+ templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),type,targetId,contentPreview (read-only)
+ full tmpl,,full page,,,,test flow2,false,0mm,0mm,0mm,0mm,Standard,,
+ full tmpl,,full page,,,,test flow3,true,0mm,0mm,0mm,0mm,Standard,,
+ full tmpl,,full page,,,,,false,0mm,0mm,0mm,0mm,Standard,,
+ full tmpl,,full page,,,,test flow5,false,0mm,0mm,0mm,0mm,Standard,,
+ ,,unreferenced page,,,,test flow,true,0mm,0mm,0mm,0mm,Standard,,
""".stripIndent()
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}
@@ -69,10 +69,34 @@ class AreasExportTest {
AreasExport.run(migration, mappingFile)
def expected = """\
- templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),contentPreview (read-only)
- tmpl with areas,,,,,,Address Content,false,0mm,0mm,0mm,0mm,
- tmpl with areas,,,,,,,true,0mm,0mm,0mm,0mm,
- tmpl with areas,,,,,,Footer,false,0mm,0mm,0mm,0mm,
+ templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),type,targetId,contentPreview (read-only)
+ tmpl with areas,,,,,,Address Content,false,0mm,0mm,0mm,0mm,Standard,,
+ tmpl with areas,,,,,,,true,0mm,0mm,0mm,0mm,Standard,,
+ tmpl with areas,,,,,,Footer,false,0mm,0mm,0mm,0mm,Standard,,
+ """.stripIndent()
+ Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
+ }
+
+ @Test
+ void exportUsesPageOrTemplateBaseTemplateAsTargetId() {
+ Path mappingFile = Paths.get(dir.path, "testProject.csv")
+ when(migration.mappingRepository.getAreaMapping(any())).thenReturn(new MappingItem.Area(null, [:], [:]))
+ when((migration.documentObjectRepository as DocumentObjectRepository).list(any())).thenReturn([
+ new DocumentObjectBuilder("tmpl with base", DocumentObjectType.Template)
+ .baseTemplateRef("G2")
+ .documentObjectRef("page with own base")
+ .build(),
+ new DocumentObjectBuilder("page with own base", DocumentObjectType.Page)
+ .baseTemplateRef("G1")
+ .content([createArea("test flow")])
+ .build(),
+ ])
+
+ AreasExport.run(migration, mappingFile)
+
+ def expected = """\
+ templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),type,targetId,contentPreview (read-only)
+ tmpl with base,,page with own base,,,,test flow,false,0mm,0mm,0mm,0mm,Standard,\$G1,
""".stripIndent()
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}
@@ -100,8 +124,8 @@ class AreasExportTest {
AreasExport.run(migration, mappingFile)
def expected = """\
- templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),contentPreview (read-only)
- ,,page with preview,,,,test flow,false,0mm,0mm,0mm,0mm,docRef: Block One;imageRef: Image One;docRef: Block Two;(+2 more)
+ templateId,templateName (read-only),pageId,pageName (read-only),pageWidth (read-only),pageHeight (read-only),interactiveFlowName,flowToNextPage,x (read-only),y (read-only),width (read-only),height (read-only),type,targetId,contentPreview (read-only)
+ ,,page with preview,,,,test flow,false,0mm,0mm,0mm,0mm,Standard,,docRef: Block One;imageRef: Image One;docRef: Block Two;(+2 more)
""".stripIndent()
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}
diff --git a/migration-examples/src/test/groovy/AreasImportTest.groovy b/migration-examples/src/test/groovy/AreasImportTest.groovy
index 2a494468..fc721eb2 100644
--- a/migration-examples/src/test/groovy/AreasImportTest.groovy
+++ b/migration-examples/src/test/groovy/AreasImportTest.groovy
@@ -3,12 +3,17 @@ import com.quadient.migration.api.dto.migrationmodel.*
import com.quadient.migration.api.dto.migrationmodel.builder.DocumentObjectBuilder
import com.quadient.migration.api.dto.migrationmodel.builder.documentcontent.AreaBuilder
import com.quadient.migration.example.common.mapping.AreasImport
+import com.quadient.migration.shared.BaseTemplateArea
+import com.quadient.migration.shared.BaseTemplatePage
import com.quadient.migration.shared.DocumentObjectType
import com.quadient.migration.shared.Position
import com.quadient.migration.shared.Size
+import com.quadient.migration.shared.SkipOptions
+import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
+import org.mockito.ArgumentCaptor
import java.nio.file.Path
import java.nio.file.Paths
@@ -91,6 +96,99 @@ class AreasImportTest {
verify(migration.mappingRepository).applyAllAreaMappings()
}
+ @Test
+ void importSetsPageBaseTemplateFromTargetIdOnStandardRows() {
+ Path mappingFile = Paths.get(dir.path, "testProject.csv")
+
+ when(migration.mappingRepository.getAreaMapping("page1")).thenReturn(new MappingItem.Area(null, [:], [:]))
+ when(migration.mappingRepository.getDocumentObjectMapping("page1")).thenReturn(
+ new MappingItem.DocumentObject(null, null, null, null, null, null, null)
+ )
+ when(migration.mappingRepository.getDocumentObjectMapping("tmpl1")).thenReturn(
+ new MappingItem.DocumentObject(null, null, null, null, null, null, null)
+ )
+ givenPageExists("page1", ["flow1", "flow2"], [false, false])
+
+ def input = """\
+ templateId,templateName,pageId,pageName,interactiveFlowName,flowToNextPage,x,y,width,height,type,targetId,contentPreview
+ tmpl1,,page1,,flow1,false,0.0mm,0.0mm,0.0mm,0.0mm,Standard,\$G1,
+ tmpl1,,page1,,flow2,false,0.0mm,0.0mm,0.0mm,0.0mm,Standard,\$G1,
+ """.stripIndent()
+ mappingFile.toFile().write(input)
+
+ AreasImport.run(migration, mappingFile)
+
+ verify(migration.mappingRepository).upsertBatch([
+ "page1": new MappingItem.DocumentObject(null, false, new BaseTemplateRef("G1"), null, null, null, new SkipOptions(false, null, null)),
+ "tmpl1": new MappingItem.DocumentObject(null, null, new BaseTemplateRef("G1"), null, null, null, null)
+ ])
+ verify(migration.mappingRepository).applyAllDocumentObjectMappings()
+ }
+
+ @Test
+ void importCreatesNewBaseTemplateFromBaseRows() {
+ Path mappingFile = Paths.get(dir.path, "testProject.csv")
+
+ when(migration.mappingRepository.getAreaMapping("page1")).thenReturn(new MappingItem.Area(null, [:], [:]))
+ when(migration.mappingRepository.getDocumentObjectMapping("page1")).thenReturn(
+ new MappingItem.DocumentObject(null, null, null, null, null, null, null)
+ )
+ when(migration.mappingRepository.getDocumentObjectMapping("tmpl1")).thenReturn(
+ new MappingItem.DocumentObject(null, null, null, null, null, null, null)
+ )
+ givenPageExists("page1", ["flow1"], [false])
+ when(migration.baseTemplateRepository.find("G1")).thenReturn(null)
+ when(migration.mappingRepository.getBaseTemplateMapping("G1")).thenReturn(new MappingItem.BaseTemplate(null, null, []))
+
+ def input = """\
+ templateId,templateName,pageId,pageName,pageWidth,pageHeight,interactiveFlowName,flowToNextPage,x,y,width,height,type,targetId,contentPreview
+ tmpl1,,page1,,,,flow1,false,0.0mm,0.0mm,0.0mm,0.0mm,Standard,\$G1,
+ G1,Base template 1,G1-P1,Page group 1,210mm,297mm,G1-P1.Area1,false,1cm,1cm,190mm,20mm,Base,,
+ G1,Base template 1,G1-P1,Page group 1,210mm,297mm,G1-P1.Area2,true,1cm,30mm,190mm,50mm,Base,,
+ """.stripIndent()
+ mappingFile.toFile().write(input)
+
+ AreasImport.run(migration, mappingFile)
+
+ def baseTemplateCaptor = ArgumentCaptor.forClass(BaseTemplate.class)
+ verify(migration.baseTemplateRepository).upsert(baseTemplateCaptor.capture())
+ Assertions.assertEquals("G1", baseTemplateCaptor.value.id)
+
+ def created = new BaseTemplatePage("Page group 1", Size.ofMillimeters(210), Size.ofMillimeters(297), [
+ new BaseTemplateArea("G1-P1.Area1", new Position(Size.ofCentimeters(1), Size.ofCentimeters(1), Size.ofMillimeters(190), Size.ofMillimeters(20)), false),
+ new BaseTemplateArea("G1-P1.Area2", new Position(Size.ofCentimeters(1), Size.ofMillimeters(30), Size.ofMillimeters(190), Size.ofMillimeters(50)), true),
+ ])
+ verify(migration.mappingRepository).upsertBatch([
+ "G1": new MappingItem.BaseTemplate("Base template 1", null, [created])
+ ])
+ verify(migration.mappingRepository).applyAllBaseTemplateMappings()
+ }
+
+ @Test
+ void importUpdatesExistingBaseTemplateMappingButKeepsItsOtherFields() {
+ Path mappingFile = Paths.get(dir.path, "testProject.csv")
+
+ def existing = new BaseTemplate("G1", "Old name", ["origin.wfd"], new CustomFieldMap(new HashMap()), "target/folder", [], null, null)
+ when(migration.baseTemplateRepository.find("G1")).thenReturn(existing)
+ when(migration.mappingRepository.getBaseTemplateMapping("G1")).thenReturn(new MappingItem.BaseTemplate(null, null, []))
+
+ def input = """\
+ templateId,templateName,pageId,pageName,pageWidth,pageHeight,interactiveFlowName,flowToNextPage,x,y,width,height,type,targetId,contentPreview
+ G1,,G1-P1,Page group 1,210mm,297mm,G1-P1.Area1,false,1cm,1cm,190mm,20mm,Base,,
+ """.stripIndent()
+ mappingFile.toFile().write(input)
+
+ AreasImport.run(migration, mappingFile)
+
+ def created = new BaseTemplatePage("Page group 1", Size.ofMillimeters(210), Size.ofMillimeters(297), [
+ new BaseTemplateArea("G1-P1.Area1", new Position(Size.ofCentimeters(1), Size.ofCentimeters(1), Size.ofMillimeters(190), Size.ofMillimeters(20)), false),
+ ])
+ verify(migration.mappingRepository).upsertBatch([
+ "G1": new MappingItem.BaseTemplate("Old name", "target/folder", [created])
+ ])
+ verify(migration.mappingRepository).applyAllBaseTemplateMappings()
+ }
+
static Area createArea(String flowName, boolean flowToNextPage) {
def areaBuilder = new AreaBuilder()
.position(new Position(Size.ofMillimeters(0), Size.ofMillimeters(0), Size.ofMillimeters(0), Size.ofMillimeters(0)))
diff --git a/migration-examples/src/test/groovy/DisplayRulesMappingExportTest.groovy b/migration-examples/src/test/groovy/DisplayRulesMappingExportTest.groovy
index 2489b755..09a82f0b 100644
--- a/migration-examples/src/test/groovy/DisplayRulesMappingExportTest.groovy
+++ b/migration-examples/src/test/groovy/DisplayRulesMappingExportTest.groovy
@@ -1,6 +1,8 @@
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.api.dto.migrationmodel.VariableStructureRef
import com.quadient.migration.data.Active
import com.quadient.migration.example.common.mapping.DisplayRulesExport
@@ -25,10 +27,10 @@ class DisplayRulesMappingExportTest {
when(migration.displayRuleRepository.listAll()).thenReturn([
new DisplayRule("empty", null, [], new CustomFieldMap([:]), null, null, null, null, true, [], null, null, null, null),
- new DisplayRule("full", "full", ["foo", "bar"], new CustomFieldMap([:]), null, null, null, new DisplayRuleRef("targetId1"), false, [], null, "targetFolder1", "baseTemplate1", new VariableStructureRef("varStruct1")),
+ new DisplayRule("full", "full", ["foo", "bar"], new CustomFieldMap([:]), null, null, null, new DisplayRuleRef("targetId1"), false, [], null, "targetFolder1", new LiteralBaseTemplatePath("baseTemplate1"), new VariableStructureRef("varStruct1")),
new DisplayRule("with-variable-structure", "with-var-struct", [], new CustomFieldMap([:]), null, null, null, null, true, [], null, null, null, new VariableStructureRef("varStruct2")),
new DisplayRule("overridden empty", null, [], new CustomFieldMap([:]), null, null, null, null, true, [], null, null, null, null),
- new DisplayRule("overridden full", "full", ["foo", "bar"], new CustomFieldMap(["originalName": "originalFull"]), null, null, null, new DisplayRuleRef("targetId2"), false, [], null, "targetFolder2", "baseTemplate2", null),
+ new DisplayRule("overridden full", "full", ["foo", "bar"], new CustomFieldMap(["originalName": "originalFull"]), null, null, null, new DisplayRuleRef("targetId2"), false, [], null, "targetFolder2", new BaseTemplateRef("baseTemplate2"), null),
])
when(migration.statusTrackingRepository.findLastEventRelevantToOutput(any(), any(), any())).thenReturn(new Active())
@@ -41,7 +43,7 @@ class DisplayRulesMappingExportTest {
full,full,false,baseTemplate1,targetFolder1,targetId1,varStruct1,Active,,[foo; bar],
with-variable-structure,with-var-struct,true,,,,varStruct2,Active,,[],
overridden empty,,true,,,,,Active,,[],
- overridden full,full,false,baseTemplate2,targetFolder2,targetId2,,Active,originalFull,[foo; bar],
+ overridden full,full,false,\$baseTemplate2,targetFolder2,targetId2,,Active,originalFull,[foo; bar],
""".stripIndent()
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}
diff --git a/migration-examples/src/test/groovy/DisplayRulesMappingImportTest.groovy b/migration-examples/src/test/groovy/DisplayRulesMappingImportTest.groovy
index bb763dc4..7f6bc8f6 100644
--- a/migration-examples/src/test/groovy/DisplayRulesMappingImportTest.groovy
+++ b/migration-examples/src/test/groovy/DisplayRulesMappingImportTest.groovy
@@ -1,5 +1,7 @@
import com.quadient.migration.api.InspireOutput
import com.quadient.migration.api.Migration
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.api.dto.migrationmodel.builder.DisplayRuleBuilder
import com.quadient.migration.data.Active
@@ -22,169 +24,49 @@ class DisplayRulesMappingImportTest {
File dir
@Test
- void overridesDisplayRuleName() {
+ void overridesAllMappableFields() {
def migration = Utils.mockMigration()
Path mappingFile = Paths.get(dir.path, "testProject.csv")
def input = """\
id,name,internal,baseTemplate,targetFolder,targetId,variableStructureRef,status,originalName (read-only),originLocations (read-only)
unchanged,,true,,,,,Active,,[]
- kept,keptName,true,,,,,Active,,[]
- overridden,someName,true,,,,,Active,,[]
+ overridden,someName,false,overriddenTemplate,overriddenFolder,overriddenId,overriddenVarStruct,Active,,[]
""".stripIndent()
mappingFile.toFile().write(input)
givenExistingDisplayRule(migration, "unchanged", null, true, null, null, null, null)
givenExistingDisplayRuleMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDisplayRule(migration, "kept", "someName", true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "kept", "keptName", null, null, null, null, null)
- givenExistingDisplayRule(migration, "overridden", "previousName", true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "overridden", "previousName", null, null, null, null, null)
+ givenExistingDisplayRule(migration, "overridden", "previousName", true, "previousId", "previousTemplate", "previousFolder", "previousVarStruct")
+ givenExistingDisplayRuleMapping(migration, "overridden", "previousName", true, "previousId", "previousTemplate", "previousFolder", "previousVarStruct")
DisplayRulesImport.run(migration, mappingFile.toFile())
verify(migration.mappingRepository, times(1)).upsertBatch([
"unchanged" : new MappingItem.DisplayRule(null, null, null, null, null, true),
- "kept" : new MappingItem.DisplayRule("keptName", null, null, null, null, true),
- "overridden": new MappingItem.DisplayRule("someName", null, null, null, null, true)
+ "overridden": new MappingItem.DisplayRule("someName", "overriddenFolder", "overriddenId", new LiteralBaseTemplatePath("overriddenTemplate"), "overriddenVarStruct", false)
])
verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
}
@Test
- void overridesDisplayRuleInternal() {
+ void overridesDisplayRuleBaseTemplateRef() {
def migration = Utils.mockMigration()
Path mappingFile = Paths.get(dir.path, "testProject.csv")
def input = """\
id,name,internal,baseTemplate,targetFolder,targetId,variableStructureRef,status,originalName (read-only),originLocations (read-only)
- unchanged,,false,,,,,Active,,[]
- kept,,true,,,,,Active,,[]
- overridden,,true,,,,,Active,,[]
+ atPrefixed,,true,@someBaseTemplateId,,,,Active,,[]
+ dollarPrefixed,,true,\$anotherBaseTemplateId,,,,Active,,[]
""".stripIndent()
mappingFile.toFile().write(input)
- givenExistingDisplayRule(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDisplayRule(migration, "kept", null, true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "kept", null, true, null, null, null, null)
- givenExistingDisplayRule(migration, "overridden", null, false, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "overridden", null, false, null, null, null, null)
-
- DisplayRulesImport.run(migration, mappingFile.toFile())
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DisplayRule(null, null, null, null, null, false),
- "kept" : new MappingItem.DisplayRule(null, null, null, null, null, true),
- "overridden": new MappingItem.DisplayRule(null, null, null, null, null, true)
- ])
- verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
- }
-
- @Test
- void overridesDisplayRuleBaseTemplate() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject.csv")
- def input = """\
- id,name,internal,baseTemplate,targetFolder,targetId,variableStructureRef,status,originalName (read-only),originLocations (read-only)
- unchanged,,true,,,,,Active,,[]
- kept,,true,keptTemplate,,,,Active,,[]
- overridden,,true,overriddenTemplate,,,,Active,,[]
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDisplayRule(migration, "unchanged", null, true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDisplayRule(migration, "kept", null, true, null, "keptTemplate", null, null)
- givenExistingDisplayRuleMapping(migration, "kept", null, null, null, "keptTemplate", null, null)
- givenExistingDisplayRule(migration, "overridden", null, true, null, "previousTemplate", null, null)
- givenExistingDisplayRuleMapping(migration, "overridden", null, null, null, "previousTemplate", null, null)
+ givenExistingDisplayRule(migration, "atPrefixed", null, true, null, null, null, null)
+ givenExistingDisplayRuleMapping(migration, "atPrefixed", null, null, null, null, null, null)
+ givenExistingDisplayRule(migration, "dollarPrefixed", null, true, null, null, null, null)
+ givenExistingDisplayRuleMapping(migration, "dollarPrefixed", null, null, null, null, null, null)
DisplayRulesImport.run(migration, mappingFile.toFile())
verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DisplayRule(null, null, null, null, null, true),
- "kept" : new MappingItem.DisplayRule(null, null, null, "keptTemplate", null, true),
- "overridden": new MappingItem.DisplayRule(null, null, null, "overriddenTemplate", null, true)
- ])
- verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
- }
-
- @Test
- void overridesDisplayRuleTargetFolder() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject.csv")
- def input = """\
- id,name,internal,baseTemplate,targetFolder,targetId,variableStructureRef,status,originalName (read-only),originLocations (read-only)
- unchanged,,true,,,,,Active,,[]
- kept,,true,,keptFolder,,,Active,,[]
- overridden,,true,,overriddenFolder,,,Active,,[]
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDisplayRule(migration, "unchanged", null, true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDisplayRule(migration, "kept", null, true, null, null, "keptFolder", null)
- givenExistingDisplayRuleMapping(migration, "kept", null, null, null, null, "keptFolder", null)
- givenExistingDisplayRule(migration, "overridden", null, true, null, null, "previousFolder", null)
- givenExistingDisplayRuleMapping(migration, "overridden", null, null, null, null, "previousFolder", null)
-
- DisplayRulesImport.run(migration, mappingFile.toFile())
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DisplayRule(null, null, null, null, null, true),
- "kept" : new MappingItem.DisplayRule(null, "keptFolder", null, null, null, true),
- "overridden": new MappingItem.DisplayRule(null, "overriddenFolder", null, null, null, true)
- ])
- verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
- }
-
- @Test
- void overridesDisplayRuleTargetId() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject.csv")
- def input = """\
- id,name,internal,baseTemplate,targetFolder,targetId,variableStructureRef,status,originalName (read-only),originLocations (read-only)
- unchanged,,true,,,,,Active,,[]
- kept,,true,,,keptId,,Active,,[]
- overridden,,true,,,overriddenId,,Active,,[]
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDisplayRule(migration, "unchanged", null, true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDisplayRule(migration, "kept", null, true, "keptId", null, null, null)
- givenExistingDisplayRuleMapping(migration, "kept", null, null, "keptId", null, null, null)
- givenExistingDisplayRule(migration, "overridden", null, true, "previousId", null, null, null)
- givenExistingDisplayRuleMapping(migration, "overridden", null, null, "previousId", null, null, null)
-
- DisplayRulesImport.run(migration, mappingFile.toFile())
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DisplayRule(null, null, null, null, null, true),
- "kept" : new MappingItem.DisplayRule(null, null, "keptId", null, null, true),
- "overridden": new MappingItem.DisplayRule(null, null, "overriddenId", null, null, true)
- ])
- verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
- }
-
- @Test
- void overridesDisplayRuleVariableStructureRef() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject.csv")
- def input = """\
- id,name,internal,baseTemplate,targetFolder,targetId,variableStructureRef,status,originalName (read-only),originLocations (read-only)
- unchanged,,true,,,,,Active,,[]
- kept,,true,,,,keptVarStruct,Active,,[]
- overridden,,true,,,,overriddenVarStruct,Active,,[]
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDisplayRule(migration, "unchanged", null, true, null, null, null, null)
- givenExistingDisplayRuleMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDisplayRule(migration, "kept", null, true, null, null, null, "keptVarStruct")
- givenExistingDisplayRuleMapping(migration, "kept", null, null, null, null, null, "keptVarStruct")
- givenExistingDisplayRule(migration, "overridden", null, true, null, null, null, "previousVarStruct")
- givenExistingDisplayRuleMapping(migration, "overridden", null, null, null, null, null, "previousVarStruct")
-
- DisplayRulesImport.run(migration, mappingFile.toFile())
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DisplayRule(null, null, null, null, null, true),
- "kept" : new MappingItem.DisplayRule(null, null, null, null, "keptVarStruct", true),
- "overridden": new MappingItem.DisplayRule(null, null, null, null, "overriddenVarStruct", true)
+ "atPrefixed" : new MappingItem.DisplayRule(null, null, null, new BaseTemplateRef("someBaseTemplateId"), null, true),
+ "dollarPrefixed": new MappingItem.DisplayRule(null, null, null, new BaseTemplateRef("anotherBaseTemplateId"), null, true)
])
verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
}
@@ -233,7 +115,7 @@ class DisplayRulesMappingImportTest {
DisplayRulesImport.run(migration, mappingFile.toFile())
verify(migration.mappingRepository, times(1)).upsertBatch([
- "rule1": new MappingItem.DisplayRule("myName", "myFolder", "myId", "myTemplate", "myVarStruct", false)
+ "rule1": new MappingItem.DisplayRule("myName", "myFolder", "myId", new LiteralBaseTemplatePath("myTemplate"), "myVarStruct", false)
])
verify(migration.mappingRepository, times(1)).applyAllDisplayRuleMappings()
}
@@ -264,7 +146,8 @@ class DisplayRulesMappingImportTest {
String baseTemplate,
String targetFolder,
String variableStructureRef) {
+ def baseTemplateLocation = baseTemplate ? new LiteralBaseTemplatePath(baseTemplate) : null
when(mig.mappingRepository.getDisplayRuleMapping(id))
- .thenReturn(new MappingItem.DisplayRule(name, targetFolder, targetId, baseTemplate, variableStructureRef, internal))
+ .thenReturn(new MappingItem.DisplayRule(name, targetFolder, targetId, baseTemplateLocation, variableStructureRef, internal))
}
}
diff --git a/migration-examples/src/test/groovy/DocumentObjectsMappingExportTest.groovy b/migration-examples/src/test/groovy/DocumentObjectsMappingExportTest.groovy
index 78586dfa..e15ce6a1 100644
--- a/migration-examples/src/test/groovy/DocumentObjectsMappingExportTest.groovy
+++ b/migration-examples/src/test/groovy/DocumentObjectsMappingExportTest.groovy
@@ -37,7 +37,7 @@ class DocumentObjectsMappingExportTest {
.customFields(["originalName": "originalFull"])
.targetFolder("someDir")
.variableStructureRef("struct")
- .baseTemplate("tmpl.wfd")
+ .baseTemplateRef("tmplRef")
.build(),
])
@@ -50,7 +50,7 @@ class DocumentObjectsMappingExportTest {
empty,,Block,false,,,,Active,false,,,,[]
full,full,Page,false,tmpl.wfd,someDir,struct,Active,true,placeholder,reason,,[foo; bar]
overridden empty,,Block,false,,,,Active,false,,,,[]
- overridden full,full,Page,false,tmpl.wfd,someDir,struct,Active,false,,,originalFull,[foo; bar]
+ overridden full,full,Page,false,\$tmplRef,someDir,struct,Active,false,,,originalFull,[foo; bar]
""".stripIndent()
Assertions.assertEquals(expected, mappingFile.toFile().text.replaceAll("\\r\\n|\\r", "\n"))
}
diff --git a/migration-examples/src/test/groovy/DocumentObjectsMappingImportTest.groovy b/migration-examples/src/test/groovy/DocumentObjectsMappingImportTest.groovy
index 402d3fd3..c460150d 100644
--- a/migration-examples/src/test/groovy/DocumentObjectsMappingImportTest.groovy
+++ b/migration-examples/src/test/groovy/DocumentObjectsMappingImportTest.groovy
@@ -1,4 +1,6 @@
import com.quadient.migration.api.Migration
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.api.dto.migrationmodel.builder.DocumentObjectBuilder
import com.quadient.migration.example.common.mapping.DocumentObjectsImport
@@ -16,197 +18,49 @@ class DocumentObjectsMappingImportTest {
File dir
@Test
- void overridesDocumentObjectName() {
+ void overridesAllMappableFields() {
def migration = Utils.mockMigration()
Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
def input = """\
- id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status
- unchanged,,Block,false,[],,,,Active
- kept,keptName,Block,false,[],,,,Active
- overridden,someName,Block,false,[],,,,Active
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", "someName", false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "kept", "keptName", null, null, null, null, null)
- givenExistingDocumentObject(migration, "overridden", "previousName", false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "overridden", "previousName", null, null, null, null, null)
-
- DocumentObjectsImport.run(migration, mappingFile)
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject("keptName", false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject("someName", false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null))
- ])
- verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
- }
-
- @Test
- void overridesDocumentObjectInternal() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
- def input = """\
- id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status
- unchanged,,Block,false,[],,,,Active
- kept,,Block,true,[],,,,Active
- overridden,,Block,true,[],,,,Active
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", null, true, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "kept", null, true, null, null, null, null)
- givenExistingDocumentObject(migration, "overridden", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "overridden", null, false, null, null, null, null)
-
- DocumentObjectsImport.run(migration, mappingFile)
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject(null, true, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject(null, true, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null))
- ])
- verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
- }
-
- @Test
- void overridesDocumentObjectBaseTemplate() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
- def input = """\
- id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status
- unchanged,,Block,false,[],,,,Active
- kept,,Block,false,[],keptTemplate,,,Active
- overridden,,Block,false,[],overriddenTemplate,,,Active
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "kept", null, null, "keptTemplate", null, null, null)
- givenExistingDocumentObject(migration, "overridden", null, false, "previousTemplate", null, null, null)
- givenExistingDocumentObjectMapping(migration, "overridden", null, null, "previousTemplate", null, null, null)
-
- DocumentObjectsImport.run(migration, mappingFile)
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject(null, false, "keptTemplate", null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject(null, false, "overriddenTemplate", null, DocumentObjectType.Block, null, new SkipOptions(false, null, null))
- ])
- verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
- }
-
- @Test
- void overridesDocumentObjectTargetFolder() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
- def input = """\
- id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status
- unchanged,,Block,false,[],,,,Active
- kept,,Block,false,[],,keptFolder,,Active
- overridden,,Block,false,[],,overriddenFolder,,Active
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "kept", null, null, null, "keptFolder", null, null)
- givenExistingDocumentObject(migration, "overridden", null, false, null, "previousFolder", null, null)
- givenExistingDocumentObjectMapping(migration, "overridden", null, null, null, "previousFolder", null, null)
-
- DocumentObjectsImport.run(migration, mappingFile)
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject(null, false, null, "keptFolder", DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject(null, false, null, "overriddenFolder", DocumentObjectType.Block, null, new SkipOptions(false, null, null))
- ])
- verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
- }
-
- @Test
- void overridesVariableStructureRef() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
- def input = """\
- id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status
+ id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status,skip,skipPlaceholder,skipReason
unchanged,,Block,false,[],,,,Active
- kept,,Block,false,[],,,keptVarStructure,Active
- overridden,,Block,false,[],,,overriddenVarStructure,Active
+ overridden,someName,Page,true,[],overriddenTemplate,overriddenFolder,overriddenVarStructure,Active,true,placeholder,reason
""".stripIndent()
mappingFile.toFile().write(input)
givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", null, false, null, null, null, "keptVarStructure")
- givenExistingDocumentObjectMapping(migration, "kept", null, null, null, null, null, "keptVarStructure")
- givenExistingDocumentObject(migration, "overridden", null, false, null, null, null, "previousVarStructure")
- givenExistingDocumentObjectMapping(migration, "overridden", null, null, null, null, null, "overriddenVarStructure")
+ givenExistingDocumentObject(migration, "overridden", "previousName", false, "previousTemplate", "previousFolder", DocumentObjectType.Template, "previousVarStructure")
+ givenExistingDocumentObjectMapping(migration, "overridden", "previousName", false, "previousTemplate", "previousFolder", DocumentObjectType.Template, "previousVarStructure")
DocumentObjectsImport.run(migration, mappingFile)
verify(migration.mappingRepository, times(1)).upsertBatch([
"unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, "keptVarStructure", new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, "overriddenVarStructure", new SkipOptions(false, null, null))
+ "overridden": new MappingItem.DocumentObject("someName", true, new LiteralBaseTemplatePath("overriddenTemplate"), "overriddenFolder", DocumentObjectType.Page, "overriddenVarStructure", new SkipOptions(true, "placeholder", "reason"))
])
verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
}
@Test
- void overridesDocumentObjectType() {
+ void overridesDocumentObjectBaseTemplateRef() {
def migration = Utils.mockMigration()
Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
def input = """\
id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status
- unchanged,,Block,false,[],,,,Active
- kept,,Template,false,[],,,,Active
- overridden,,Page,false,[],,,,Active
+ atPrefixed,,Block,false,[],@someBaseTemplateId,,,Active
+ dollarPrefixed,,Block,false,[],\$anotherBaseTemplateId,,,Active
""".stripIndent()
mappingFile.toFile().write(input)
- givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "kept", null, null, null, null, DocumentObjectType.Template, null)
- givenExistingDocumentObject(migration, "overridden", null, false, null, null, DocumentObjectType.Template, null)
- givenExistingDocumentObjectMapping(migration, "overridden", null, null, null, null, DocumentObjectType.Section, null)
+ givenExistingDocumentObject(migration, "atPrefixed", null, false, null, null, null, null)
+ givenExistingDocumentObjectMapping(migration, "atPrefixed", null, null, null, null, null, null)
+ givenExistingDocumentObject(migration, "dollarPrefixed", null, false, null, null, null, null)
+ givenExistingDocumentObjectMapping(migration, "dollarPrefixed", null, null, null, null, null, null)
DocumentObjectsImport.run(migration, mappingFile)
verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Template, null, new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Page, null, new SkipOptions(false, null, null))
- ])
- verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
- }
-
- @Test
- void overridesSkipOptions() {
- def migration = Utils.mockMigration()
- Path mappingFile = Paths.get(dir.path, "testProject-variables.csv")
- def input = """\
- id,name,type,internal,originLocation,baseTemplate,targetFolder,variableStructureId,status,skip,skipPlaceholder,skipReason
- unchanged,,Block,false,[],,,,Active
- kept,,Template,false,[],,,,Active
- overridden,,Page,false,[],,,,Active,true,placeholder,reason
- """.stripIndent()
- mappingFile.toFile().write(input)
- givenExistingDocumentObject(migration, "unchanged", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "unchanged", null, null, null, null, null, null)
- givenExistingDocumentObject(migration, "kept", null, false, null, null, null, null)
- givenExistingDocumentObjectMapping(migration, "kept", null, null, null, null, DocumentObjectType.Template, null)
- givenExistingDocumentObject(migration, "overridden", null, false, null, null, DocumentObjectType.Template, null)
- givenExistingDocumentObjectMapping(migration, "overridden", null, null, null, null, DocumentObjectType.Section, null)
-
- DocumentObjectsImport.run(migration, mappingFile)
-
- verify(migration.mappingRepository, times(1)).upsertBatch([
- "unchanged" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
- "kept" : new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Template, null, new SkipOptions(false, null, null)),
- "overridden": new MappingItem.DocumentObject(null, false, null, null, DocumentObjectType.Page, null, new SkipOptions(true, "placeholder", "reason"))
+ "atPrefixed" : new MappingItem.DocumentObject(null, false, new BaseTemplateRef("someBaseTemplateId"), null, DocumentObjectType.Block, null, new SkipOptions(false, null, null)),
+ "dollarPrefixed": new MappingItem.DocumentObject(null, false, new BaseTemplateRef("anotherBaseTemplateId"), null, DocumentObjectType.Block, null, new SkipOptions(false, null, null))
])
verify(migration.mappingRepository, times(1)).applyAllDocumentObjectMappings()
}
@@ -240,7 +94,8 @@ class DocumentObjectsMappingImportTest {
String targetFolder,
DocumentObjectType type,
String varStructureRef) {
+ def baseTemplateLocation = baseTemplate ? new LiteralBaseTemplatePath(baseTemplate) : null
when(mig.mappingRepository.getDocumentObjectMapping(id))
- .thenReturn(new MappingItem.DocumentObject(name, internal, baseTemplate, targetFolder, type, varStructureRef, null))
+ .thenReturn(new MappingItem.DocumentObject(name, internal, baseTemplateLocation, targetFolder, type, varStructureRef, null))
}
}
diff --git a/migration-examples/src/test/groovy/Utils.groovy b/migration-examples/src/test/groovy/Utils.groovy
index aada7c8d..7a0bf2f7 100644
--- a/migration-examples/src/test/groovy/Utils.groovy
+++ b/migration-examples/src/test/groovy/Utils.groovy
@@ -1,6 +1,7 @@
import com.quadient.migration.api.InspireOutput
import com.quadient.migration.api.Migration
import com.quadient.migration.api.ProjectConfig
+import com.quadient.migration.api.repository.BaseTemplateRepository
import com.quadient.migration.api.repository.DisplayRuleRepository
import com.quadient.migration.api.repository.DocumentObjectRepository
import com.quadient.migration.api.repository.AttachmentRepository
@@ -34,6 +35,7 @@ static Migration mockMigration() {
def textStyleRepo = mock(TextStyleRepository.class)
def paraStyleRepo = mock(ParagraphStyleRepository.class)
def displayRuleRepo = mock(DisplayRuleRepository.class)
+ def baseTemplateRepo = mock(BaseTemplateRepository.class)
when(migration.getParagraphStyleRepository()).thenReturn(paraStyleRepo)
when(migration.getTextStyleRepository()).thenReturn(textStyleRepo)
@@ -45,6 +47,7 @@ static Migration mockMigration() {
when(migration.getVariableStructureRepository()).thenReturn(structureRepo)
when(migration.getMappingRepository()).thenReturn(mappingRepo)
when(migration.getDisplayRuleRepository()).thenReturn(displayRuleRepo)
+ when(migration.getBaseTemplateRepository()).thenReturn(baseTemplateRepo)
def previewProvider = new PreviewProvider(docObjectRepo, imageRepo, attachmentRepo, varRepo)
when(migration.getPreviewProvider()).thenReturn(previewProvider)
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/Migration.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/Migration.kt
index b24d4141..5ec3b59f 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/Migration.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/Migration.kt
@@ -96,6 +96,7 @@ class Migration(val config: MigConfig, val projectConfig: ProjectConfig) {
single()
single()
single()
+ single()
single()
single()
single()
@@ -128,6 +129,7 @@ class Migration(val config: MigConfig, val projectConfig: ProjectConfig) {
val paragraphStyleRepository: ParagraphStyleRepository by lazy { koin.get() }
val variableStructureRepository: VariableStructureRepository by lazy { koin.get() }
val displayRuleRepository: DisplayRuleRepository by lazy { koin.get() }
+ val baseTemplateRepository: BaseTemplateRepository by lazy { koin.get() }
val imageRepository: ImageRepository by lazy { koin.get() }
val attachmentRepository: AttachmentRepository by lazy { koin.get() }
val statusTrackingRepository: StatusTrackingRepository by lazy { koin.get() }
@@ -164,6 +166,7 @@ class Migration(val config: MigConfig, val projectConfig: ProjectConfig) {
repositories.add(paragraphStyleRepository)
repositories.add(variableStructureRepository)
repositories.add(displayRuleRepository)
+ repositories.add(baseTemplateRepository)
repositories.add(imageRepository)
repositories.add(attachmentRepository)
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/BaseTemplate.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/BaseTemplate.kt
new file mode 100644
index 00000000..e2c9cc29
--- /dev/null
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/BaseTemplate.kt
@@ -0,0 +1,15 @@
+package com.quadient.migration.api.dto.migrationmodel
+
+import com.quadient.migration.shared.BaseTemplatePage
+import kotlin.time.Instant
+
+data class BaseTemplate(
+ override val id: String,
+ override var name: String? = null,
+ override var originLocations: List = emptyList(),
+ override var customFields: CustomFieldMap,
+ var targetFolder: String? = null,
+ var pages: List = emptyList(),
+ override var created: Instant? = null,
+ override var lastUpdated: Instant? = null,
+) : MigrationObject
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DisplayRule.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DisplayRule.kt
index 0d830336..41de9e01 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DisplayRule.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DisplayRule.kt
@@ -17,10 +17,12 @@ data class DisplayRule @JvmOverloads constructor(
val metadata: List = emptyList(),
val subject: String? = null,
val targetFolder: String? = null,
- val baseTemplate: String? = null,
+ val baseTemplate: BaseTemplateLocation? = null,
val variableStructureRef: VariableStructureRef? = null,
) : MigrationObject, RefValidatable {
override fun collectRefs(): Set[ {
- return (definition?.collectRefs() ?: emptySet()) + setOfNotNull(variableStructureRef, targetId)
+ val baseTemplateRef = baseTemplate as? BaseTemplateRef
+
+ return (definition?.collectRefs() ?: emptySet()) + setOfNotNull(variableStructureRef, targetId, baseTemplateRef)
}
}
\ No newline at end of file
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DocumentObject.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DocumentObject.kt
index b30e940c..b824edaa 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DocumentObject.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/DocumentObject.kt
@@ -16,7 +16,7 @@ data class DocumentObject(
var targetFolder: String? = null,
var displayRuleRef: DisplayRuleRef? = null,
var variableStructureRef: VariableStructureRef? = null,
- var baseTemplate: String? = null,
+ var baseTemplate: BaseTemplateLocation? = null,
var options: DocumentObjectOptions? = null,
var pdfMetadata: PdfMetadata? = null,
override var created: Instant? = null,
@@ -35,6 +35,8 @@ data class DocumentObject(
val pdfMetadataRefs = pdfMetadata?.collectRefs().orEmpty()
- return contentRefs + pdfMetadataRefs + setOfNotNull(displayRuleRef, variableStructureRef)
+ val baseTemplateRef = baseTemplate as? BaseTemplateRef
+
+ return contentRefs + pdfMetadataRefs + setOfNotNull(displayRuleRef, variableStructureRef, baseTemplateRef)
}
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Mapping.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Mapping.kt
index 59d8692b..f172b530 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Mapping.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Mapping.kt
@@ -13,7 +13,7 @@ sealed class MappingItem {
data class DocumentObject(
override var name: String?,
var internal: Boolean?,
- var baseTemplate: String?,
+ var baseTemplate: BaseTemplateLocation?,
var targetFolder: String?,
var type: DocumentObjectType?,
var variableStructureRef: String?,
@@ -98,11 +98,17 @@ sealed class MappingItem {
override var name: String?,
var targetFolder: String?,
var targetId: String?,
- var baseTemplate: String?,
+ var baseTemplate: BaseTemplateLocation?,
var variableStructureRef: String?,
var internal: Boolean?,
) : MappingItem()
+ data class BaseTemplate(
+ override var name: String?,
+ var targetFolder: String?,
+ var pages: List = emptyList(),
+ ) : MappingItem()
+
data class Table(
override var name: String? = null,
val tables: List = emptyList(),
@@ -123,7 +129,7 @@ sealed class MappingItem {
MappingItemEntity.DocumentObject(
name = this.name,
internal = this.internal,
- baseTemplate = this.baseTemplate,
+ baseTemplate = this.baseTemplate?.toDb(),
targetFolder = this.targetFolder,
type = this.type,
variableStructureRef = this.variableStructureRef,
@@ -135,6 +141,12 @@ sealed class MappingItem {
name = this.name, areas = this.areas, flowToNextPage = this.flowToNextPage
)
+ is MappingItem.BaseTemplate -> MappingItemEntity.BaseTemplate(
+ name = this.name,
+ targetFolder = this.targetFolder,
+ pages = this.pages,
+ )
+
is MappingItem.Image -> {
MappingItemEntity.Image(
name = this.name,
@@ -221,7 +233,7 @@ sealed class MappingItem {
internal = this.internal,
variableStructureRef = this.variableStructureRef,
targetFolder = this.targetFolder,
- baseTemplate = this.baseTemplate,
+ baseTemplate = this.baseTemplate?.toDb(),
)
is MappingItem.Table -> MappingItemEntity.Table(
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Ref.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Ref.kt
index d39e17cc..f2df16fb 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Ref.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/Ref.kt
@@ -1,6 +1,8 @@
package com.quadient.migration.api.dto.migrationmodel
import com.quadient.migration.persistence.migrationmodel.ColumnLayoutEntity
+import com.quadient.migration.persistence.migrationmodel.BaseTemplateEntityRef
+import com.quadient.migration.persistence.migrationmodel.BaseTemplateLocationEntity
import com.quadient.migration.persistence.migrationmodel.DisplayRuleEntityRef
import com.quadient.migration.persistence.migrationmodel.DocumentObjectEntityRef
import com.quadient.migration.persistence.migrationmodel.FirstMatchEntity
@@ -8,6 +10,7 @@ import com.quadient.migration.persistence.migrationmodel.HyperlinkEntity
import com.quadient.migration.persistence.migrationmodel.ImageEntityRef
import com.quadient.migration.persistence.migrationmodel.AttachmentEntityRef
import com.quadient.migration.persistence.migrationmodel.BarcodeEntity
+import com.quadient.migration.persistence.migrationmodel.LiteralBaseTemplatePathEntity
import com.quadient.migration.persistence.migrationmodel.ParagraphStyleEntityRef
import com.quadient.migration.persistence.migrationmodel.ResourceEntityRef
import com.quadient.migration.persistence.migrationmodel.StringEntity
@@ -138,6 +141,36 @@ data class VariableStructureRef(override val id: String) : Ref(id) {
fun toDb() = VariableStructureEntityRef(id)
}
+sealed interface BaseTemplateLocation {
+ companion object {
+ fun fromDb(entity: BaseTemplateLocationEntity): BaseTemplateLocation = when (entity) {
+ is LiteralBaseTemplatePathEntity -> LiteralBaseTemplatePath.fromDb(entity)
+ is BaseTemplateEntityRef -> BaseTemplateRef.fromDb(entity)
+ }
+ }
+}
+
+fun BaseTemplateLocation.toDb(): BaseTemplateLocationEntity = when (this) {
+ is LiteralBaseTemplatePath -> this.toDb()
+ is BaseTemplateRef -> this.toDb()
+}
+
+data class LiteralBaseTemplatePath(val path: String) : BaseTemplateLocation {
+ companion object {
+ fun fromDb(entity: LiteralBaseTemplatePathEntity) = LiteralBaseTemplatePath(entity.path)
+ }
+
+ fun toDb() = LiteralBaseTemplatePathEntity(path)
+}
+
+data class BaseTemplateRef(override val id: String) : Ref(id), BaseTemplateLocation {
+ companion object {
+ fun fromDb(entity: BaseTemplateEntityRef) = BaseTemplateRef(entity.id)
+ }
+
+ fun toDb() = BaseTemplateEntityRef(id)
+}
+
data class StringValue(val value: String) : VariableStringContent {
override val pathName = "str"
override fun toPreview(nameResolver: (DocumentContent) -> String?): String =
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DisplayRuleBuilder.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DisplayRuleBuilder.kt
index ab35c2b9..e06860ed 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DisplayRuleBuilder.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DisplayRuleBuilder.kt
@@ -11,6 +11,7 @@ import com.quadient.migration.api.dto.migrationmodel.builder.components.HasMetad
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasSubject
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasTargetFolder
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasVariableStructureRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.shared.BinOp
import com.quadient.migration.shared.Binary
import com.quadient.migration.shared.BinaryOrGroup
@@ -35,7 +36,7 @@ class DisplayRuleBuilder(id: String) : DtoBuilderBase = mutableListOf()
override var variableStructureRef: VariableStructureRef? = null
- override var baseTemplate: String? = null
+ override var baseTemplate: BaseTemplateLocation? = null
override var targetFolder: String? = null
var definition: DisplayRuleDefinition? = null
var targetId: String? = null
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DocumentObjectBuilder.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DocumentObjectBuilder.kt
index d0e06c74..39fd0c9e 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DocumentObjectBuilder.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/DocumentObjectBuilder.kt
@@ -19,6 +19,7 @@ import com.quadient.migration.api.dto.migrationmodel.builder.components.HasSubje
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasTargetFolder
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasVariableStructureRef
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectOptions
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.shared.DocumentObjectType
import com.quadient.migration.api.dto.migrationmodel.EmailOptions
import com.quadient.migration.shared.MetadataEntry
@@ -47,7 +48,7 @@ class DocumentObjectBuilder(id: String, private val type: DocumentObjectType) :
override var variableStructureRef: VariableStructureRef? = null
override var internal: Boolean = false
override var targetFolder: String? = null
- override var baseTemplate: String? = null
+ override var baseTemplate: BaseTemplateLocation? = null
override var subject: String? = null
override var options: DocumentObjectOptions? = null
override var metadata: MutableList = mutableListOf()
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/SnippetBuilder.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/SnippetBuilder.kt
index 088f60a6..dcc064b9 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/SnippetBuilder.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/SnippetBuilder.kt
@@ -17,6 +17,7 @@ import com.quadient.migration.api.dto.migrationmodel.builder.components.HasSubje
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasTargetFolder
import com.quadient.migration.api.dto.migrationmodel.builder.components.HasVariableStructureRef
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectOptions
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.shared.DocumentObjectType
import com.quadient.migration.shared.MetadataEntry
import com.quadient.migration.shared.SkipOptions
@@ -54,7 +55,7 @@ class FirstMatchSnippetBuilder(id: String) : DtoBuilderBase = mutableListOf()
@@ -118,7 +119,7 @@ class SimpleSnippetBuilder(id: String) : DtoBuilderBase = mutableListOf()
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/components/HasBaseTemplate.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/components/HasBaseTemplate.kt
index 3b6306f9..101ed110 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/components/HasBaseTemplate.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/dto/migrationmodel/builder/components/HasBaseTemplate.kt
@@ -1,13 +1,52 @@
package com.quadient.migration.api.dto.migrationmodel.builder.components
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplate
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
+
@Suppress("UNCHECKED_CAST")
interface HasBaseTemplate {
- var baseTemplate: String?
+ var baseTemplate: BaseTemplateLocation?
/**
* Override the default base template for this object.
- * @param baseTemplate Path to the base template to use for this document object.
+ * @param baseTemplateLocation Location (literal path or base template reference) of the base template to use for this object.
+ * @return This builder instance for method chaining.
+ */
+ fun baseTemplate(baseTemplateLocation: BaseTemplateLocation?) =
+ apply { this.baseTemplate = baseTemplateLocation } as T
+
+ /**
+ * Overrides the default base template for this object with a literal ICM path.
+ * @param path Path to the base template to use for this object.
+ * @return This builder instance for method chaining.
+ */
+ @Deprecated(
+ message = "Use baseTemplatePath() for a literal path or baseTemplateRef() for a reference to a BaseTemplate migration object instead.",
+ replaceWith = ReplaceWith("baseTemplatePath(baseTemplate)"),
+ )
+ fun baseTemplate(path: String?) = apply { this.baseTemplate = path?.let { LiteralBaseTemplatePath(it) } } as T
+
+ /**
+ * Overrides the default base template for this object with a literal ICM path.
+ * @param path Path to the base template to use for this object.
+ * @return This builder instance for method chaining.
+ */
+ fun baseTemplatePath(path: String?) = apply { this.baseTemplate = path?.let { LiteralBaseTemplatePath(it) } } as T
+
+ /**
+ * Overrides the default base template for this object with a reference to a [BaseTemplate] migration object.
+ * @param id ID of the [BaseTemplate] migration object to use for this object.
+ * @return This builder instance for method chaining.
+ */
+ fun baseTemplateRef(id: String?) = apply { this.baseTemplate = id?.let { BaseTemplateRef(it) } } as T
+
+ /**
+ * Overrides the default base template for this object with a reference to a [BaseTemplate] migration object.
+ * @param baseTemplate The [BaseTemplate] migration object to use for this object.
* @return This builder instance for method chaining.
*/
- fun baseTemplate(baseTemplate: String?) = apply { this.baseTemplate = baseTemplate } as T
+ fun baseTemplateRef(baseTemplate: BaseTemplate) =
+ apply { this.baseTemplate = BaseTemplateRef(baseTemplate.id) } as T
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/BaseTemplateRepository.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/BaseTemplateRepository.kt
new file mode 100644
index 00000000..c57ee9aa
--- /dev/null
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/BaseTemplateRepository.kt
@@ -0,0 +1,96 @@
+package com.quadient.migration.api.repository
+
+import com.quadient.migration.api.ProjectName
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplate
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
+import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
+import com.quadient.migration.api.dto.migrationmodel.MigrationObject
+import com.quadient.migration.persistence.table.BaseTemplateTable
+import com.quadient.migration.persistence.table.DocumentObjectTable
+import com.quadient.migration.tools.concat
+import kotlin.time.Clock
+import kotlin.time.toJavaInstant
+import kotlinx.serialization.json.Json
+import java.sql.Types
+import org.jetbrains.exposed.v1.core.ResultRow
+import org.jetbrains.exposed.v1.core.eq
+import org.jetbrains.exposed.v1.jdbc.selectAll
+import org.jetbrains.exposed.v1.jdbc.transactions.transaction
+import org.jetbrains.exposed.v1.jdbc.upsertReturning
+
+class BaseTemplateRepository(projectName: ProjectName) :
+ Repository(BaseTemplateTable, projectName.name) {
+
+ override fun fromDb(row: ResultRow): BaseTemplate {
+ return BaseTemplate(
+ id = row[BaseTemplateTable.id].value,
+ name = row[BaseTemplateTable.name],
+ customFields = CustomFieldMap(row[BaseTemplateTable.customFields].toMutableMap()),
+ lastUpdated = row[BaseTemplateTable.lastUpdated],
+ created = row[BaseTemplateTable.created],
+ originLocations = row[BaseTemplateTable.originLocations],
+ targetFolder = row[BaseTemplateTable.targetFolder],
+ pages = row[BaseTemplateTable.pages],
+ )
+ }
+
+ override fun findUsages(id: String): List {
+ return transaction {
+ DocumentObjectTable.selectAll().where { DocumentObjectTable.projectName eq projectName }
+ .map { DocumentObjectTable.fromResultRow(it) }
+ .filter { it.collectRefs().any { ref -> ref is BaseTemplateRef && ref.id == id } }
+ .distinct()
+ }
+ }
+
+ override fun upsert(dto: BaseTemplate) {
+ upsertInternal {
+ val existingItem = table.selectAll().where(filter(dto.id)).firstOrNull()?.let(::fromDb)
+
+ val now = Clock.System.now()
+
+ table.upsertReturning(table.id, table.projectName) {
+ it[BaseTemplateTable.id] = dto.id
+ it[BaseTemplateTable.projectName] = this@BaseTemplateRepository.projectName
+ it[BaseTemplateTable.name] = dto.name
+ it[BaseTemplateTable.originLocations] = existingItem?.originLocations.concat(dto.originLocations).distinct()
+ it[BaseTemplateTable.customFields] = dto.customFields.inner
+ it[BaseTemplateTable.created] = existingItem?.created ?: now
+ it[BaseTemplateTable.lastUpdated] = now
+ it[BaseTemplateTable.targetFolder] = dto.targetFolder
+ it[BaseTemplateTable.pages] = dto.pages
+ }.first()
+ }
+ }
+
+ override fun upsertBatch(dtos: Collection) {
+ if (dtos.isEmpty()) return
+
+ val columns = listOf(
+ "id", "project_name", "name", "origin_locations", "custom_fields",
+ "created", "last_updated", "target_folder", "pages"
+ )
+ val sql = createSql(columns, dtos.size)
+ val now = Clock.System.now()
+
+ upsertBatchInternal(dtos) {
+ val stmt = it.prepareStatement(sql)
+ var index = 1
+ dtos.forEach { dto ->
+ val existingItem = find(dto.id)
+
+ stmt.setString(index++, dto.id)
+ stmt.setString(index++, this@BaseTemplateRepository.projectName)
+ stmt.setString(index++, dto.name)
+ stmt.setArray(index++, it.createArrayOf("text", existingItem?.originLocations.concat(dto.originLocations).distinct().toTypedArray()))
+ stmt.setObject(index++, Json.encodeToString(dto.customFields.inner), Types.OTHER)
+ stmt.setTimestamp(index++, java.sql.Timestamp.from((existingItem?.created ?: now).toJavaInstant()))
+ stmt.setTimestamp(index++, java.sql.Timestamp.from(now.toJavaInstant()))
+ stmt.setString(index++, dto.targetFolder)
+ stmt.setObject(index++, Json.encodeToString(dto.pages), Types.OTHER)
+ }
+
+ stmt.executeUpdate()
+ }
+ }
+}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DisplayRuleRepository.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DisplayRuleRepository.kt
index 25500358..e3ece305 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DisplayRuleRepository.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DisplayRuleRepository.kt
@@ -1,11 +1,13 @@
package com.quadient.migration.api.repository
import com.quadient.migration.api.ProjectName
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
import com.quadient.migration.api.dto.migrationmodel.MigrationObject
import com.quadient.migration.api.dto.migrationmodel.VariableStructureRef
+import com.quadient.migration.api.dto.migrationmodel.toDb
import com.quadient.migration.persistence.table.DisplayRuleTable
import com.quadient.migration.persistence.table.DocumentObjectTable
import com.quadient.migration.service.deploy.utility.ResourceType
@@ -32,7 +34,7 @@ class DisplayRuleRepository(projectName: ProjectName, private val statusTracking
lastUpdated = row[DisplayRuleTable.lastUpdated],
created = row[DisplayRuleTable.created],
definition = row[DisplayRuleTable.definition],
- baseTemplate = row[DisplayRuleTable.baseTemplate],
+ baseTemplate = row[DisplayRuleTable.baseTemplate]?.let { BaseTemplateLocation.fromDb(it) },
metadata = row[DisplayRuleTable.metadata],
subject = row[DisplayRuleTable.subject],
internal = row[DisplayRuleTable.internal],
@@ -85,7 +87,7 @@ class DisplayRuleRepository(projectName: ProjectName, private val statusTracking
stmt.setBoolean(index++, dto.internal)
stmt.setString(index++, dto.subject)
stmt.setString(index++, dto.targetFolder)
- stmt.setString(index++, dto.baseTemplate)
+ stmt.setObject(index++, dto.baseTemplate?.let { Json.encodeToString(it.toDb()) }, Types.OTHER)
stmt.setString(index++, dto.variableStructureRef?.id)
stmt.setObject(index++, Json.encodeToString(dto.metadata), Types.OTHER)
}
@@ -117,7 +119,7 @@ class DisplayRuleRepository(projectName: ProjectName, private val statusTracking
it[DisplayRuleTable.internal] = dto.internal
it[DisplayRuleTable.subject] = dto.subject
it[DisplayRuleTable.targetFolder] = dto.targetFolder
- it[DisplayRuleTable.baseTemplate] = dto.baseTemplate
+ it[DisplayRuleTable.baseTemplate] = dto.baseTemplate?.toDb()
it[DisplayRuleTable.variableStructureRef] = dto.variableStructureRef?.id
it[DisplayRuleTable.metadata] = dto.metadata
}.first()
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DocumentObjectRepository.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DocumentObjectRepository.kt
index bbc3c4ad..7893e441 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DocumentObjectRepository.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/DocumentObjectRepository.kt
@@ -85,7 +85,7 @@ class DocumentObjectRepository(projectName: ProjectName, private val statusTrack
stmt.setTimestamp(index++, java.sql.Timestamp.from(now.toJavaInstant()))
stmt.setString(index++, dto.displayRuleRef?.id)
stmt.setString(index++, dto.variableStructureRef?.id)
- stmt.setString(index++, dto.baseTemplate)
+ stmt.setObject(index++, dto.baseTemplate?.let { Json.encodeToString(it.toDb()) }, Types.OTHER)
stmt.setObject(index++, dto.options?.let { Json.encodeToString(it.toDb()) }, Types.OTHER)
stmt.setObject(index++, dto.pdfMetadata?.let { Json.encodeToString(it.toDb()) }, Types.OTHER)
stmt.setObject(index++, dto.metadata.let { Json.encodeToString(it) }, Types.OTHER)
@@ -128,7 +128,7 @@ class DocumentObjectRepository(projectName: ProjectName, private val statusTrack
it[DocumentObjectTable.lastUpdated] = now
it[DocumentObjectTable.displayRuleRef] = dto.displayRuleRef?.id
it[DocumentObjectTable.variableStructureRef] = dto.variableStructureRef?.id
- it[DocumentObjectTable.baseTemplate] = dto.baseTemplate
+ it[DocumentObjectTable.baseTemplate] = dto.baseTemplate?.toDb()
it[DocumentObjectTable.documentObjectOptions] = dto.options?.toDb()
it[DocumentObjectTable.pdfMetadata] = dto.pdfMetadata?.toDb()
it[DocumentObjectTable.metadata] = dto.metadata
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/MappingRepository.kt b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/MappingRepository.kt
index 982edcc4..267a24c2 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/api/repository/MappingRepository.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/api/repository/MappingRepository.kt
@@ -2,13 +2,13 @@ package com.quadient.migration.api.repository
import com.quadient.migration.api.ProjectName
import com.quadient.migration.api.dto.migrationmodel.Attachment
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplate
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.Image
import com.quadient.migration.api.dto.migrationmodel.ParagraphStyle
import com.quadient.migration.api.dto.migrationmodel.TextStyle
import com.quadient.migration.api.dto.migrationmodel.Variable
-import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
import com.quadient.migration.api.dto.migrationmodel.Mapping
import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.api.dto.migrationmodel.MigrationObject
@@ -16,6 +16,7 @@ import com.quadient.migration.api.dto.migrationmodel.VariableStructure
import com.quadient.migration.persistence.migrationmodel.MappingItemEntity
import com.quadient.migration.persistence.repository.MappingInternalRepository
import com.quadient.migration.persistence.table.AttachmentTable
+import com.quadient.migration.persistence.table.BaseTemplateTable
import com.quadient.migration.persistence.table.DisplayRuleTable
import com.quadient.migration.persistence.table.DocumentObjectTable
import com.quadient.migration.persistence.table.ImageTable
@@ -38,6 +39,7 @@ class MappingRepository(
private val variableRepository: VariableRepository,
private val variableStructureRepository: VariableStructureRepository,
private val displayRuleRepository: DisplayRuleRepository,
+ private val baseTemplateRepository: BaseTemplateRepository,
) {
private val logger by logger()
private val internalRepository = MappingInternalRepository(projectName.name)
@@ -59,6 +61,7 @@ class MappingRepository(
applyAllVariableStructureMappings()
applyAllDisplayRuleMappings()
applyAllTableMappings(onError)
+ applyAllBaseTemplateMappings()
}
fun upsert(id: String, mapping: MappingItem): Mapping {
@@ -276,18 +279,9 @@ class MappingRepository(
fun applyVariableStructureMapping(id: String) {
val mapping = internalRepository.find(id)
- val structure = variableStructureRepository.find(id) ?: VariableStructure(
- id = id,
- name = null,
- originLocations = emptyList(),
- customFields = CustomFieldMap(),
- created = kotlin.time.Clock.System.now(),
- lastUpdated = kotlin.time.Clock.System.now(),
- structure = mutableMapOf(),
- languageVariable = null,
- )
-
- if (mapping == null) {
+ val structure = variableStructureRepository.find(id)
+
+ if (mapping == null || structure == null) {
return
}
@@ -316,6 +310,27 @@ class MappingRepository(
displayRuleRepository.upsert(mapping.apply(displayRule))
}
+ fun getBaseTemplateMapping(id: String): MappingItem.BaseTemplate {
+ return (internalRepository.find(id) ?: MappingItemEntity.BaseTemplate(
+ name = null, targetFolder = null, pages = emptyList()
+ )).toDto() as MappingItem.BaseTemplate
+ }
+
+ fun applyBaseTemplateMapping(id: String) {
+ val mapping = internalRepository.find(id)
+ val baseTemplate = baseTemplateRepository.find(id)
+
+ if (mapping == null || baseTemplate == null) {
+ return
+ }
+
+ baseTemplateRepository.upsert(mapping.apply(baseTemplate))
+ }
+
+ fun applyAllBaseTemplateMappings() {
+ applyAllResourceMappings(baseTemplateRepository, BaseTemplateTable)
+ }
+
fun deleteAll() {
internalRepository.deleteAll()
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntity.kt b/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntity.kt
index 353934da..59b0b36f 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntity.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntity.kt
@@ -22,6 +22,7 @@ import com.quadient.migration.api.dto.migrationmodel.VariableStructure as Variab
import com.quadient.migration.api.dto.migrationmodel.Area as AreaModel
import com.quadient.migration.api.dto.migrationmodel.DisplayRule as DisplayRuleModel
import com.quadient.migration.api.dto.migrationmodel.Table as TableModel
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplate as BaseTemplateModel
class MappingEntity(id: EntityID) : CompositeEntity(id) {
companion object : CompositeEntityClass(MappingTable)
@@ -54,6 +55,7 @@ sealed class MappingItemEntity {
is VariableStructure -> this.apply(entity as VariableStructureModel)
is DisplayRule -> this.apply(entity as DisplayRuleModel)
is Table -> this.apply(entity as DocumentObjectModel, onError)
+ is BaseTemplate -> this.apply(entity as BaseTemplateModel)
}
}
@@ -61,7 +63,7 @@ sealed class MappingItemEntity {
data class DocumentObject(
override val name: String?,
val internal: Boolean?,
- val baseTemplate: String?,
+ val baseTemplate: BaseTemplateLocationEntity?,
val targetFolder: String?,
val variableStructureRef: String?,
@SerialName("documentObjectType") val type: DocumentObjectType?,
@@ -72,7 +74,7 @@ sealed class MappingItemEntity {
return item.copy(
name = name,
internal = internal ?: false,
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { BaseTemplateLocation.fromDb(it) },
targetFolder = targetFolder,
type = type ?: item.type,
variableStructureRef = variableStructureRef?.let { VariableStructureRef(it) },
@@ -108,6 +110,21 @@ sealed class MappingItemEntity {
}
}
+ @Serializable
+ data class BaseTemplate(
+ override val name: String?,
+ val targetFolder: String?,
+ val pages: List = emptyList(),
+ ) : MappingItemEntity() {
+ fun apply(item: BaseTemplateModel): BaseTemplateModel {
+ return item.copy(
+ name = name,
+ targetFolder = targetFolder,
+ pages = pages,
+ )
+ }
+ }
+
@Serializable
data class Image(
override val name: String?,
@@ -234,7 +251,7 @@ sealed class MappingItemEntity {
override var name: String?,
val targetFolder: String?,
var targetId: String?,
- val baseTemplate: String?,
+ val baseTemplate: BaseTemplateLocationEntity?,
val variableStructureRef: String?,
var internal: Boolean?,
) : MappingItemEntity() {
@@ -242,7 +259,7 @@ sealed class MappingItemEntity {
return item.copy(
name = name,
targetFolder = targetFolder,
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { BaseTemplateLocation.fromDb(it) },
variableStructureRef = variableStructureRef?.let { VariableStructureRef(it) },
targetId = targetId?.let { DisplayRuleRef(it) },
internal = internal ?: true
@@ -358,7 +375,7 @@ sealed class MappingItemEntity {
MappingItem.DocumentObject(
name = this.name,
internal = this.internal,
- baseTemplate = this.baseTemplate,
+ baseTemplate = this.baseTemplate?.let { BaseTemplateLocation.fromDb(it) },
targetFolder = this.targetFolder,
type = this.type,
variableStructureRef = this.variableStructureRef,
@@ -368,6 +385,12 @@ sealed class MappingItemEntity {
is Area -> MappingItem.Area(name = this.name, areas = this.areas)
+ is BaseTemplate -> MappingItem.BaseTemplate(
+ name = this.name,
+ targetFolder = this.targetFolder,
+ pages = this.pages,
+ )
+
is Image -> {
MappingItem.Image(
name = this.name,
@@ -455,7 +478,7 @@ sealed class MappingItemEntity {
internal = this.internal,
variableStructureRef = this.variableStructureRef,
targetFolder = this.targetFolder,
- baseTemplate = this.baseTemplate,
+ baseTemplate = this.baseTemplate?.let { BaseTemplateLocation.fromDb(it) },
)
is Table -> MappingItem.Table(
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/RefEntity.kt b/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/RefEntity.kt
index 3d5b6fac..72744bac 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/RefEntity.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/persistence/migrationmodel/RefEntity.kt
@@ -4,6 +4,7 @@ import com.quadient.migration.shared.Color
import com.quadient.migration.shared.ShapePath
import com.quadient.migration.shared.Position
import com.quadient.migration.shared.Size
+import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
@@ -43,6 +44,17 @@ data class AttachmentEntityRef(val id: String) : ResourceEntityRef
@Serializable
data class VariableStructureEntityRef(val id: String) : RefEntity
+@Serializable
+sealed interface BaseTemplateLocationEntity
+
+@Serializable
+@SerialName("BaseTemplatePath")
+data class LiteralBaseTemplatePathEntity(val path: String) : BaseTemplateLocationEntity
+
+@Serializable
+@SerialName("BaseTemplateRef")
+data class BaseTemplateEntityRef(val id: String) : RefEntity, BaseTemplateLocationEntity
+
@Serializable
data class StringEntity(val value: String) : VariableStringContentEntity
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/BaseTemplateTable.kt b/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/BaseTemplateTable.kt
new file mode 100644
index 00000000..0be62259
--- /dev/null
+++ b/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/BaseTemplateTable.kt
@@ -0,0 +1,10 @@
+package com.quadient.migration.persistence.table
+
+import com.quadient.migration.shared.BaseTemplatePage
+import kotlinx.serialization.json.Json
+import org.jetbrains.exposed.v1.json.jsonb
+
+object BaseTemplateTable : MigrationObjectTable("base_template") {
+ val targetFolder = varchar("target_folder", 255).nullable()
+ val pages = jsonb]>("pages", Json)
+}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DisplayRuleTable.kt b/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DisplayRuleTable.kt
index 8fd8e733..0b01a938 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DisplayRuleTable.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DisplayRuleTable.kt
@@ -1,5 +1,6 @@
package com.quadient.migration.persistence.table
+import com.quadient.migration.persistence.migrationmodel.BaseTemplateLocationEntity
import com.quadient.migration.shared.DisplayRuleDefinition
import com.quadient.migration.shared.MetadataEntry
import kotlinx.serialization.json.Json
@@ -11,7 +12,7 @@ object DisplayRuleTable : MigrationObjectTable("display_rule") {
val internal = bool("internal")
val subject = varchar("subject", 255).nullable()
val targetFolder = varchar("target_folder", 255).nullable()
- val baseTemplate = varchar("base_template", 255).nullable()
+ val baseTemplate = jsonb("base_template", Json).nullable()
val variableStructureRef = varchar("variable_structure_ref", 255).nullable()
val metadata = jsonb>("metadata", Json)
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DocumentObjectTable.kt b/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DocumentObjectTable.kt
index 3bd78d19..59964a9e 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DocumentObjectTable.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/persistence/table/DocumentObjectTable.kt
@@ -1,5 +1,6 @@
package com.quadient.migration.persistence.table
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
import com.quadient.migration.api.dto.migrationmodel.DocumentContent
@@ -7,6 +8,7 @@ import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectOptions
import com.quadient.migration.api.dto.migrationmodel.PdfMetadata
import com.quadient.migration.api.dto.migrationmodel.VariableStructureRef
+import com.quadient.migration.persistence.migrationmodel.BaseTemplateLocationEntity
import com.quadient.migration.persistence.migrationmodel.DocumentContentEntity
import com.quadient.migration.persistence.migrationmodel.PdfMetadataEntity
import com.quadient.migration.persistence.migrationmodel.DocumentObjectOptionsEntity
@@ -24,7 +26,7 @@ object DocumentObjectTable : MigrationObjectTable("document_object") {
val targetFolder = varchar("target_folder", 255).nullable()
val displayRuleRef = varchar("display_rule_ref", 255).nullable()
val variableStructureRef = varchar("variable_structure_ref", 255).nullable()
- val baseTemplate = varchar("base_template", 255).nullable()
+ val baseTemplate = jsonb("base_template", Json).nullable()
val documentObjectOptions = jsonb("options", Json).nullable()
val pdfMetadata = jsonb("pdf_metadata", Json).nullable()
val metadata = jsonb>("metadata", Json)
@@ -45,7 +47,7 @@ object DocumentObjectTable : MigrationObjectTable("document_object") {
lastUpdated = result[lastUpdated],
displayRuleRef = result[displayRuleRef]?.let { DisplayRuleRef(it) },
variableStructureRef = result[variableStructureRef]?.let { VariableStructureRef(it) },
- baseTemplate = result[baseTemplate],
+ baseTemplate = result[baseTemplate]?.let { BaseTemplateLocation.fromDb(it) },
options = result[documentObjectOptions]?.let(DocumentObjectOptions::fromDb),
pdfMetadata = result[pdfMetadata]?.let(PdfMetadata::fromDb),
metadata = result[metadata],
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/persistence/upgrade/V16__add_base_template.kt b/migration-library/src/main/kotlin/com/quadient/migration/persistence/upgrade/V16__add_base_template.kt
new file mode 100644
index 00000000..fab0745e
--- /dev/null
+++ b/migration-library/src/main/kotlin/com/quadient/migration/persistence/upgrade/V16__add_base_template.kt
@@ -0,0 +1,60 @@
+package com.quadient.migration.persistence.upgrade
+
+import org.flywaydb.core.api.migration.BaseJavaMigration
+import org.flywaydb.core.api.migration.Context
+
+class V16__add_base_template : BaseJavaMigration() {
+ override fun migrate(context: Context) {
+ val connection = context.connection
+ connection.createStatement().use { stmt ->
+ stmt.execute(
+ """
+ CREATE TABLE IF NOT EXISTS base_template (
+ id VARCHAR(255) NOT NULL,
+ project_name VARCHAR(50) NOT NULL,
+ name VARCHAR(255),
+ origin_locations TEXT[] NOT NULL,
+ custom_fields JSONB NOT NULL,
+ last_updated TIMESTAMP NOT NULL,
+ created TIMESTAMP NOT NULL,
+ target_folder VARCHAR(255),
+ pages JSONB NOT NULL,
+ PRIMARY KEY (id, project_name)
+ )
+ """.trimIndent()
+ )
+
+ for (table in listOf("document_object", "display_rule")) {
+ stmt.execute(
+ """
+ ALTER TABLE $table
+ ALTER COLUMN base_template TYPE JSONB
+ USING (
+ CASE
+ WHEN base_template IS NULL THEN NULL
+ ELSE jsonb_build_object('type', 'BaseTemplatePath', 'path', base_template)
+ END
+ )
+ """.trimIndent()
+ )
+ }
+
+ for (type in listOf("DocumentObject", "DisplayRule")) {
+ stmt.execute(
+ """
+ UPDATE mapping
+ SET mappings = jsonb_set(
+ mappings,
+ '{baseTemplate}',
+ jsonb_build_object('type', 'BaseTemplatePath', 'path', mappings->>'baseTemplate'),
+ false
+ )
+ WHERE type = '$type'
+ AND mappings ? 'baseTemplate'
+ AND jsonb_typeof(mappings->'baseTemplate') = 'string'
+ """.trimIndent()
+ )
+ }
+ }
+ }
+}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/DeployPhaseUtils.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/DeployPhaseUtils.kt
index 34a3a876..9e6cc7ad 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/DeployPhaseUtils.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/DeployPhaseUtils.kt
@@ -3,10 +3,13 @@ package com.quadient.migration.service
import com.quadient.migration.api.ProjectConfig
import com.quadient.migration.api.dto.migrationmodel.Attachment
import com.quadient.migration.api.dto.migrationmodel.AttachmentRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateLocation
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.DocumentContent
import com.quadient.migration.api.dto.migrationmodel.Image
import com.quadient.migration.api.dto.migrationmodel.ImageRef
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.api.dto.migrationmodel.ResourceRef
import com.quadient.migration.api.repository.Repository
import com.quadient.migration.shared.IcmPath
@@ -59,9 +62,16 @@ fun resolveTargetDir(defaultTargetFolder: IcmPath? = null, specificTargetFolder:
}
}
-fun getBaseTemplateFullPath(config: ProjectConfig, documentObjectBaseTemplatePath: String?): IcmPath {
- val baseTemplatePath = documentObjectBaseTemplatePath ?: config.baseTemplatePath
- val path = baseTemplatePath.toIcmPath()
+fun getBaseTemplateFullPath(config: ProjectConfig, documentObjectBaseTemplate: BaseTemplateLocation?): IcmPath {
+ val literalPath = when (documentObjectBaseTemplate) {
+ is LiteralBaseTemplatePath -> documentObjectBaseTemplate.path
+ is BaseTemplateRef -> error(
+ "Referencing base templates by id ('${documentObjectBaseTemplate.id}') is not yet supported during deployment." // TODO d.svitak - handle
+ )
+
+ null -> config.baseTemplatePath
+ }
+ val path = literalPath.toIcmPath()
if (path.isAbsolute()) return path
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/RefCollector.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/RefCollector.kt
index c52f0ebd..8195c0b1 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/RefCollector.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/RefCollector.kt
@@ -1,6 +1,7 @@
package com.quadient.migration.service
import com.quadient.migration.api.dto.migrationmodel.AttachmentRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectRef
import com.quadient.migration.api.dto.migrationmodel.ImageRef
@@ -12,6 +13,7 @@ import com.quadient.migration.api.dto.migrationmodel.TextStyleRef
import com.quadient.migration.api.dto.migrationmodel.VariableRef
import com.quadient.migration.api.dto.migrationmodel.VariableStructureRef
import com.quadient.migration.api.repository.AttachmentRepository
+import com.quadient.migration.api.repository.BaseTemplateRepository
import com.quadient.migration.api.repository.DisplayRuleRepository
import com.quadient.migration.api.repository.DocumentObjectRepository
import com.quadient.migration.api.repository.ImageRepository
@@ -29,6 +31,7 @@ class RefCollector(
private val displayRuleRepository: DisplayRuleRepository,
private val variableRepository: VariableRepository,
private val variableStructureRepository: VariableStructureRepository,
+ private val baseTemplateRepository: BaseTemplateRepository,
) {
fun collectAllRefs(obj: T, breakFn: (MigrationObject) -> Boolean = { true }): Set[ {
return obj.collectAllRefs(breakFn)
@@ -61,6 +64,7 @@ class RefCollector(
is TextStyleRef -> textStyleRepository.findOrFail(ref.id)
is VariableRef -> variableRepository.findOrFail(ref.id)
is VariableStructureRef -> variableStructureRepository.findOrFail(ref.id)
+ is BaseTemplateRef -> baseTemplateRepository.findOrFail(ref.id)
}
private fun T.traverse(
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/ReferenceValidator.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/ReferenceValidator.kt
index 97201b6d..a6bfa11b 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/ReferenceValidator.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/ReferenceValidator.kt
@@ -1,6 +1,7 @@
package com.quadient.migration.service
import com.quadient.migration.api.dto.migrationmodel.*
+import com.quadient.migration.api.repository.BaseTemplateRepository
import com.quadient.migration.api.repository.DisplayRuleRepository
import com.quadient.migration.api.repository.DocumentObjectRepository
import com.quadient.migration.api.repository.AttachmentRepository
@@ -19,6 +20,7 @@ class ReferenceValidator(
private val displayRuleRepository: DisplayRuleRepository,
private val imageRepository: ImageRepository,
private val attachmentRepository: AttachmentRepository,
+ private val baseTemplateRepository: BaseTemplateRepository,
) {
/**
* Validates all objects in the database.
@@ -156,6 +158,17 @@ class ReferenceValidator(
missingRefs.add(current)
}
}
+
+ is BaseTemplateRef -> {
+ val baseTemplate = baseTemplateRepository.find(current.id)
+
+ if (baseTemplate != null) {
+ validatedRefs.add(current)
+ alreadyValidRefs.add(current)
+ } else {
+ missingRefs.add(current)
+ }
+ }
}
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/StylesValidator.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/StylesValidator.kt
index 5c7cc097..8e1ad7d3 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/StylesValidator.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/StylesValidator.kt
@@ -4,6 +4,7 @@ import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectRef
import com.quadient.migration.api.dto.migrationmodel.AttachmentRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
import com.quadient.migration.api.dto.migrationmodel.ImageRef
import com.quadient.migration.api.dto.migrationmodel.ParagraphStyle
import com.quadient.migration.api.dto.migrationmodel.ParagraphStyleRef
@@ -77,6 +78,7 @@ class StylesValidator(
is AttachmentRef -> {}
is VariableRef -> {}
is VariableStructureRef -> {}
+ is BaseTemplateRef -> {}
}
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/DeployClient.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/DeployClient.kt
index c9fb6571..784c68db 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/DeployClient.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/DeployClient.kt
@@ -9,6 +9,7 @@ import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectRef
import com.quadient.migration.api.dto.migrationmodel.Attachment
import com.quadient.migration.api.dto.migrationmodel.AttachmentRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.Image
import com.quadient.migration.api.dto.migrationmodel.ImageRef
@@ -401,7 +402,7 @@ sealed class DeployClient(
val dependencies = mutableListOf()
this.collectRefs().forEach { ref ->
when (ref) {
- is DisplayRuleRef, is TextStyleRef, is ParagraphStyleRef, is VariableRef, is VariableStructureRef -> {}
+ is DisplayRuleRef, is TextStyleRef, is ParagraphStyleRef, is VariableRef, is VariableStructureRef, is BaseTemplateRef -> {}
is ImageRef -> {}
is AttachmentRef -> {}
is DocumentObjectRef -> {
@@ -421,7 +422,7 @@ sealed class DeployClient(
this.collectRefs().forEach { ref ->
when (ref) {
- is DisplayRuleRef, is TextStyleRef, is ParagraphStyleRef, is VariableRef, is VariableStructureRef -> {}
+ is DisplayRuleRef, is TextStyleRef, is ParagraphStyleRef, is VariableRef, is VariableStructureRef, is BaseTemplateRef -> {}
is ResourceRef -> resources.add(ref)
is DocumentObjectRef -> {
val model = documentObjectRepository.find(ref.id)
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/InteractiveDeployClient.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/InteractiveDeployClient.kt
index 37bb072f..15b01c9e 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/InteractiveDeployClient.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/InteractiveDeployClient.kt
@@ -5,6 +5,7 @@ import com.quadient.migration.api.repository.StatusTrackingRepository
import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.Attachment
import com.quadient.migration.api.dto.migrationmodel.AttachmentRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
import com.quadient.migration.api.dto.migrationmodel.CustomFieldMap
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
@@ -455,7 +456,7 @@ open class InteractiveDeployClient(
resources.addAll(model.getAllExternalDisplayRules())
}
- is ParagraphStyleRef, is AttachmentRef, is ImageRef, is TextStyleRef, is VariableRef, is VariableStructureRef -> {}
+ is ParagraphStyleRef, is AttachmentRef, is ImageRef, is TextStyleRef, is VariableRef, is VariableStructureRef, is BaseTemplateRef -> {}
}
}
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/utility/ProgressReport.kt b/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/utility/ProgressReport.kt
index fccbd810..692a2a79 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/utility/ProgressReport.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/service/deploy/utility/ProgressReport.kt
@@ -5,6 +5,7 @@ import com.quadient.migration.api.dto.migrationmodel.DocumentObject
import com.quadient.migration.api.dto.migrationmodel.Image
import com.quadient.migration.api.dto.migrationmodel.Attachment
import com.quadient.migration.api.dto.migrationmodel.AttachmentRef
+import com.quadient.migration.api.dto.migrationmodel.BaseTemplateRef
import com.quadient.migration.api.dto.migrationmodel.DisplayRule
import com.quadient.migration.api.dto.migrationmodel.DisplayRuleRef
import com.quadient.migration.api.dto.migrationmodel.DocumentObjectRef
@@ -247,6 +248,7 @@ class ProgressReporterImpl(
is ParagraphStyleRef -> null
is VariableRef -> null
is VariableStructureRef -> null
+ is BaseTemplateRef -> null
}
if (resource != null) {
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/shared/BaseTemplatePage.kt b/migration-library/src/main/kotlin/com/quadient/migration/shared/BaseTemplatePage.kt
new file mode 100644
index 00000000..11f1edad
--- /dev/null
+++ b/migration-library/src/main/kotlin/com/quadient/migration/shared/BaseTemplatePage.kt
@@ -0,0 +1,18 @@
+package com.quadient.migration.shared
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class BaseTemplateArea(
+ var interactiveFlowName: String,
+ var position: Position? = null,
+ var flowToNextPage: Boolean = false,
+)
+
+@Serializable
+data class BaseTemplatePage(
+ var name: String? = null,
+ var pageWidth: Size? = null,
+ var pageHeight: Size? = null,
+ var areas: List = emptyList(),
+)
diff --git a/migration-library/src/main/kotlin/com/quadient/migration/shared/JrdDefinition.kt b/migration-library/src/main/kotlin/com/quadient/migration/shared/JrdDefinition.kt
index 2b430b44..9dec9916 100644
--- a/migration-library/src/main/kotlin/com/quadient/migration/shared/JrdDefinition.kt
+++ b/migration-library/src/main/kotlin/com/quadient/migration/shared/JrdDefinition.kt
@@ -20,6 +20,7 @@ import com.quadient.migration.service.inspirebuilder.removeDataFromVariablePath
import com.quadient.migration.service.inspirebuilder.toScript
import com.quadient.migration.service.inspirebuilder.resolve
import com.quadient.migration.service.inspirebuilder.variableToScript
+import com.quadient.migration.service.getBaseTemplateFullPath
import com.quadient.migration.shared.BinOp.Equals
import com.quadient.migration.shared.BinOp.EqualsCaseInsensitive
import com.quadient.migration.shared.BinOp.GreaterOrEqualThan
@@ -91,7 +92,7 @@ data class JrdDefinition(
variable
}
- val baseTemplate = IcmPath.from(rule.baseTemplate ?: projectConfig.baseTemplatePath)
+ val baseTemplate = getBaseTemplateFullPath(projectConfig, rule.baseTemplate)
.toMapInteractive(projectConfig.interactiveTenant)
val ruleDef = requireNotNull(rule.definition) { "Display rule '${rule.id}' cannot be deployed because it has missing definition" }
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/persistence/DisplayRuleRepositoryTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/persistence/DisplayRuleRepositoryTest.kt
index 6988d41d..2e1339f1 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/persistence/DisplayRuleRepositoryTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/persistence/DisplayRuleRepositoryTest.kt
@@ -21,7 +21,7 @@ class DisplayRuleRepositoryTest {
.originLocations(listOf("test1", "test2"))
.definition(DisplayRuleDefinition(group = Group(items = emptyList(), operator = GroupOp.Or, false)))
.metadata("meta1") { string("val") }
- .baseTemplate("icm://Interactive/StandardPackage/BaseTemplates/templ.wfd")
+ .baseTemplatePath("icm://Interactive/StandardPackage/BaseTemplates/templ.wfd")
.internal(false)
.targetFolder("targetFolder")
.subject("Test Subject")
@@ -46,7 +46,7 @@ class DisplayRuleRepositoryTest {
.originLocations(listOf("origin1"))
.definition(DisplayRuleDefinition(group = Group(items = emptyList(), operator = GroupOp.And, false)))
.metadata("meta1") { string("val") }
- .baseTemplate("icm://Interactive/StandardPackage/BaseTemplates/templ.wfd")
+ .baseTemplatePath("icm://Interactive/StandardPackage/BaseTemplates/templ.wfd")
.internal(false)
.targetFolder("targetFolder")
.subject("Test Subject")
@@ -60,7 +60,7 @@ class DisplayRuleRepositoryTest {
.originLocations(listOf("origin2"))
.definition(DisplayRuleDefinition(group = Group(items = emptyList(), operator = GroupOp.Or, true)))
.metadata("meta1") { string("val") }
- .baseTemplate("icm://Interactive/StandardPackage/BaseTemplates/templ.wfd")
+ .baseTemplatePath("icm://Interactive/StandardPackage/BaseTemplates/templ.wfd")
.internal(false)
.targetFolder("targetFolder")
.subject("Test Subject")
@@ -101,4 +101,4 @@ class DisplayRuleRepositoryTest {
updatedBlock1.name.shouldBeEqualTo("Updated Rule 1")
updatedBlock2.name.shouldBeEqualTo("Updated Rule 2")
}
-}
\ No newline at end of file
+}
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/persistence/DocumentObjectRepositoryTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/persistence/DocumentObjectRepositoryTest.kt
index 8ffe2eb4..b85e3029 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/persistence/DocumentObjectRepositoryTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/persistence/DocumentObjectRepositoryTest.kt
@@ -57,7 +57,7 @@ class DocumentObjectRepositoryTest {
.internal(true)
.targetFolder("acquired")
.displayRuleRef("someruleref")
- .baseTemplate("someBaseTemplate")
+ .baseTemplatePath("someBaseTemplate")
.skip("reason", "placeholder")
.variableStructureRef("someVarStructRef")
.subject("somesubject")
@@ -76,7 +76,7 @@ class DocumentObjectRepositoryTest {
// given
val block1 = DocumentObjectBuilder("block1", DocumentObjectType.Block)
.internal(true)
- .baseTemplate("baseTemplate1")
+ .baseTemplatePath("baseTemplate1")
.customFields(mutableMapOf("field1" to "value1"))
.originLocations(listOf("origin1"))
.content(listOf(Paragraph("content1")))
@@ -91,7 +91,7 @@ class DocumentObjectRepositoryTest {
val block2 = DocumentObjectBuilder("block2", DocumentObjectType.Block)
.internal(false)
- .baseTemplate("baseTemplate2")
+ .baseTemplatePath("baseTemplate2")
.customFields(mutableMapOf("field2" to "value2"))
.originLocations(listOf("origin2"))
.content(listOf(Paragraph("content2")))
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/persistence/MappingRepositoryTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/persistence/MappingRepositoryTest.kt
index 82593aab..1acdc6e1 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/persistence/MappingRepositoryTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/persistence/MappingRepositoryTest.kt
@@ -7,6 +7,7 @@ import com.quadient.migration.api.dto.migrationmodel.MappingItem
import com.quadient.migration.api.dto.migrationmodel.VariableStructure
import com.quadient.migration.api.dto.migrationmodel.VariableStructureRef
import com.quadient.migration.api.repository.AttachmentRepository
+import com.quadient.migration.api.repository.BaseTemplateRepository
import com.quadient.migration.api.repository.DisplayRuleRepository
import com.quadient.migration.api.repository.DocumentObjectRepository
import com.quadient.migration.api.repository.ImageRepository
@@ -15,6 +16,11 @@ import com.quadient.migration.api.repository.ParagraphStyleRepository
import com.quadient.migration.api.repository.TextStyleRepository
import com.quadient.migration.api.repository.VariableRepository
import com.quadient.migration.api.repository.VariableStructureRepository
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
+import com.quadient.migration.shared.BaseTemplateArea
+import com.quadient.migration.shared.BaseTemplatePage
+import com.quadient.migration.shared.Position
+import com.quadient.migration.shared.Size
import com.quadient.migration.shared.VariablePathData
import com.quadient.migration.tools.aProjectConfig
import com.quadient.migration.tools.aVariable
@@ -38,6 +44,7 @@ class MappingRepositoryTest {
val variableRepository = mockk()
val variableStructureRepository = mockk()
val displayRuleRepository = mockk()
+ val baseTemplateRepository = mockk()
private val repo = MappingRepository(
ProjectName(projectConfig.name),
@@ -49,6 +56,7 @@ class MappingRepositoryTest {
variableRepository,
variableStructureRepository,
displayRuleRepository,
+ baseTemplateRepository,
)
@Test
@@ -118,7 +126,7 @@ class MappingRepositoryTest {
name = "new name",
targetFolder = "/some/folder",
targetId = "target-123",
- baseTemplate = "template-base",
+ baseTemplate = LiteralBaseTemplatePath("template-base"),
variableStructureRef = "ref",
internal = true,
)
@@ -133,11 +141,40 @@ class MappingRepositoryTest {
it.name == "new name" &&
it.targetFolder == "/some/folder" &&
it.targetId?.id == "target-123" &&
- it.baseTemplate == "template-base" &&
+ it.baseTemplate == LiteralBaseTemplatePath("template-base") &&
it.internal &&
it.variableStructureRef == VariableStructureRef("ref")
}
)
}
}
+
+ @Test
+ fun `apply base template mapping does nothing when base template does not exist`() {
+ every { baseTemplateRepository.find("baseTemplateId") } returns null
+ every { baseTemplateRepository.upsert(any()) } just runs
+ repo.upsert(
+ "baseTemplateId", MappingItem.BaseTemplate(
+ name = "New Base Template",
+ targetFolder = "icm://Interactive/Tenant/BaseTemplates/some.wfd",
+ pages = listOf(
+ BaseTemplatePage(
+ name = "Page1",
+ pageWidth = Size.ofMillimeters(210.0),
+ pageHeight = Size.ofMillimeters(297.0),
+ areas = listOf(
+ BaseTemplateArea(
+ interactiveFlowName = "Flow1",
+ position = Position(Size.ofMillimeters(1.0), Size.ofMillimeters(2.0), Size.ofMillimeters(3.0), Size.ofMillimeters(4.0)),
+ )
+ ),
+ )
+ ),
+ )
+ )
+
+ repo.applyBaseTemplateMapping("baseTemplateId")
+
+ verify(exactly = 0) { baseTemplateRepository.upsert(any()) }
+ }
}
\ No newline at end of file
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntityTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntityTest.kt
index 6c37f950..5f4dc414 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntityTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/persistence/migrationmodel/MappingEntityTest.kt
@@ -9,6 +9,7 @@ import com.quadient.migration.api.dto.migrationmodel.builder.ParagraphStyleBuild
import com.quadient.migration.api.dto.migrationmodel.builder.TableBuilder
import com.quadient.migration.api.dto.migrationmodel.builder.TextStyleBuilder
import com.quadient.migration.api.dto.migrationmodel.builder.documentcontent.AreaBuilder
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.shared.Alignment
import com.quadient.migration.shared.Color
import com.quadient.migration.shared.DataType
@@ -69,7 +70,7 @@ class MappingEntityTest {
val mapping = MappingItemEntity.DocumentObject(
name = "new name",
internal = false,
- baseTemplate = "new base",
+ baseTemplate = LiteralBaseTemplatePathEntity("new base"),
targetFolder = "new folder",
type = Block,
variableStructureRef = "new structure",
@@ -89,7 +90,7 @@ class MappingEntityTest {
assertEquals(result.name, "new name")
assertEquals(result.internal, false)
- assertEquals(result.baseTemplate, "new base")
+ assertEquals(result.baseTemplate, LiteralBaseTemplatePath("new base"))
assertEquals(result.targetFolder, "new folder")
assertEquals(result.type, Block)
assertEquals(result.variableStructureRef?.id, "new structure")
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/persistence/upgrade/V16MigrationTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/persistence/upgrade/V16MigrationTest.kt
new file mode 100644
index 00000000..3cfdc913
--- /dev/null
+++ b/migration-library/src/test/kotlin/com/quadient/migration/persistence/upgrade/V16MigrationTest.kt
@@ -0,0 +1,167 @@
+package com.quadient.migration.persistence.upgrade
+
+import com.quadient.migration.Postgres.Companion.POSTGRES_CONTAINER
+import kotlinx.serialization.json.Json
+import org.flywaydb.core.Flyway
+import org.jetbrains.exposed.v1.jdbc.Database
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertNull
+import org.junit.jupiter.api.Test
+import org.testcontainers.postgresql.PostgreSQLContainer
+import java.sql.Connection
+import java.sql.DriverManager
+
+/**
+ * Integration test for V16 migration that introduces the base_template table and converts the
+ * document_object/display_rule base_template columns (and their mapping counterparts) from a plain
+ * path string into a discriminated jsonb reference (path or id).
+ */
+class V16MigrationTest {
+
+ @Test
+ fun `V16 migration converts base template references to jsonb`() {
+ PostgreSQLContainer(POSTGRES_CONTAINER).use { postgres ->
+ postgres.start()
+
+ Database.connect(
+ url = postgres.jdbcUrl,
+ driver = "org.postgresql.Driver",
+ user = postgres.username,
+ password = postgres.password
+ )
+
+ Flyway.configure()
+ .dataSource(postgres.jdbcUrl, postgres.username, postgres.password)
+ .locations("classpath:com/quadient/migration/persistence/upgrade")
+ .target("15")
+ .load()
+ .migrate()
+
+ connection(postgres).use { conn ->
+ insertDocumentObject(conn, "doc-with-base-template", "templates/base.xml")
+ insertDocumentObject(conn, "doc-without-base-template", null)
+ insertDisplayRule(conn, "rule-with-base-template", "templates/base-rule.xml")
+ insertDisplayRule(conn, "rule-without-base-template", null)
+
+ insertMapping(
+ conn, "map-doc", "DocumentObject",
+ """{"name":"mapped","baseTemplate":"templates/mapped.xml"}"""
+ )
+ insertMapping(
+ conn, "map-doc-null", "DocumentObject",
+ """{"name":"mapped","baseTemplate":null}"""
+ )
+ insertMapping(
+ conn, "map-rule", "DisplayRule",
+ """{"name":"mapped","baseTemplate":"templates/mapped-rule.xml"}"""
+ )
+ insertMapping(
+ conn, "map-area", "Area",
+ """{"name":"mapped","areas":{}}"""
+ )
+ }
+
+ Flyway.configure()
+ .dataSource(postgres.jdbcUrl, postgres.username, postgres.password)
+ .locations("classpath:com/quadient/migration/persistence/upgrade")
+ .target("16")
+ .load()
+ .migrate()
+
+ connection(postgres).use { conn ->
+ assertJsonEquals(
+ """{"type":"BaseTemplatePath","path":"templates/base.xml"}""",
+ queryColumn(conn, "document_object", "base_template", "doc-with-base-template")!!
+ )
+ assertNull(queryColumn(conn, "document_object", "base_template", "doc-without-base-template"))
+
+ assertJsonEquals(
+ """{"type":"BaseTemplatePath","path":"templates/base-rule.xml"}""",
+ queryColumn(conn, "display_rule", "base_template", "rule-with-base-template")!!
+ )
+ assertNull(queryColumn(conn, "display_rule", "base_template", "rule-without-base-template"))
+
+ assertJsonEquals(
+ """{"name":"mapped","baseTemplate":{"type":"BaseTemplatePath","path":"templates/mapped.xml"}}""",
+ queryMapping(conn, "map-doc", "DocumentObject")
+ )
+ assertJsonEquals(
+ """{"name":"mapped","baseTemplate":null}""",
+ queryMapping(conn, "map-doc-null", "DocumentObject")
+ )
+ assertJsonEquals(
+ """{"name":"mapped","baseTemplate":{"type":"BaseTemplatePath","path":"templates/mapped-rule.xml"}}""",
+ queryMapping(conn, "map-rule", "DisplayRule")
+ )
+ assertJsonEquals(
+ """{"name":"mapped","areas":{}}""",
+ queryMapping(conn, "map-area", "Area")
+ )
+ }
+ }
+ }
+
+ private fun insertDocumentObject(conn: Connection, id: String, baseTemplate: String?) {
+ conn.prepareStatement(
+ """
+ INSERT INTO document_object (id, project_name, name, origin_locations, custom_fields, type, internal, metadata, skip, base_template, last_updated, created)
+ VALUES (?, 'test', ?, '{}', '{}', 'Block', true, '[]', '{"skipped":false,"reason":null,"placeholder":null}'::jsonb, ?, NOW(), NOW())
+ """.trimIndent()
+ ).apply {
+ setString(1, id)
+ setString(2, id)
+ setString(3, baseTemplate)
+ }.executeUpdate()
+ }
+
+ private fun insertDisplayRule(conn: Connection, id: String, baseTemplate: String?) {
+ conn.prepareStatement(
+ """
+ INSERT INTO display_rule (id, project_name, name, origin_locations, custom_fields, internal, metadata, base_template, last_updated, created)
+ VALUES (?, 'test', ?, '{}', '{}', true, '{}', ?, NOW(), NOW())
+ """.trimIndent()
+ ).apply {
+ setString(1, id)
+ setString(2, id)
+ setString(3, baseTemplate)
+ }.executeUpdate()
+ }
+
+ private fun insertMapping(conn: Connection, id: String, type: String, mappings: String) {
+ conn.prepareStatement(
+ """
+ INSERT INTO mapping (id, type, project_name, mappings)
+ VALUES (?, ?, 'test', ?::jsonb)
+ """.trimIndent()
+ ).apply {
+ setString(1, id)
+ setString(2, type)
+ setString(3, mappings)
+ }.executeUpdate()
+ }
+
+ private fun queryColumn(conn: Connection, table: String, column: String, id: String): String? {
+ val rs = conn.prepareStatement("SELECT $column::text AS value FROM $table WHERE id = ?")
+ .apply { setString(1, id) }
+ .executeQuery()
+ assert(rs.next()) { "Expected row '$id' in '$table' to exist" }
+ return rs.getString("value")
+ }
+
+ private fun queryMapping(conn: Connection, id: String, type: String): String {
+ val rs = conn.prepareStatement("SELECT mappings::text FROM mapping WHERE id = ? AND type = ?")
+ .apply {
+ setString(1, id)
+ setString(2, type)
+ }
+ .executeQuery()
+ assert(rs.next()) { "Expected mapping row '$id' of type '$type' to exist" }
+ return rs.getString("mappings")
+ }
+
+ private fun connection(postgres: PostgreSQLContainer): Connection =
+ DriverManager.getConnection(postgres.jdbcUrl, postgres.username, postgres.password)
+
+ private fun assertJsonEquals(expected: String, actual: String) =
+ assertEquals(Json.parseToJsonElement(expected), Json.parseToJsonElement(actual))
+}
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/service/DeployPhaseUtilsTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/service/DeployPhaseUtilsTest.kt
index cbd4f99a..f949e8ca 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/service/DeployPhaseUtilsTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/service/DeployPhaseUtilsTest.kt
@@ -2,6 +2,7 @@ package com.quadient.migration.service
import com.quadient.migration.service.inspirebuilder.appendExtensionIfMissing
import com.quadient.migration.service.inspirebuilder.extractExtensionFromPath
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.tools.aProjectConfig
import com.quadient.migration.tools.shouldBeEqualTo
import org.junit.jupiter.api.Test
@@ -21,14 +22,14 @@ class DeployPhaseUtilsTest {
@Test
fun `specific base template path is preferred over the project config one`() {
val baseTemplatePath = "icm://Interactive/Vital/BaseTemplates/MyBaseTemplate.wfd"
- val result = getBaseTemplateFullPath(projectConfig, baseTemplatePath).toString()
+ val result = getBaseTemplateFullPath(projectConfig, LiteralBaseTemplatePath(baseTemplatePath)).toString()
result.shouldBeEqualTo(baseTemplatePath)
}
@Test
fun `path not starting with icm is handled as relative`() {
- val result = getBaseTemplateFullPath(projectConfig, "/projectA/AddressBT.wfd").toString()
+ val result = getBaseTemplateFullPath(projectConfig, LiteralBaseTemplatePath("/projectA/AddressBT.wfd")).toString()
result.shouldBeEqualTo("icm://Interactive/${projectConfig.interactiveTenant}/BaseTemplates/projectA/AddressBT.wfd")
}
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/service/ReferenceValidatorTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/service/ReferenceValidatorTest.kt
index f05df432..7003c2b3 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/service/ReferenceValidatorTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/service/ReferenceValidatorTest.kt
@@ -6,6 +6,7 @@ import com.quadient.migration.api.dto.migrationmodel.ParagraphStyleRef
import com.quadient.migration.api.dto.migrationmodel.TextStyleRef
import com.quadient.migration.shared.DocumentObjectType
import com.quadient.migration.tools.aBlockDto
+import com.quadient.migration.tools.aBaseTemplateRepository
import com.quadient.migration.tools.aDisplayRuleRepository
import com.quadient.migration.tools.aDocumentObjectRepository
import com.quadient.migration.tools.aAttachmentRepository
@@ -32,6 +33,7 @@ class ReferenceValidatorTest {
val displayRuleRepository = aDisplayRuleRepository()
val imageRepository = aImageRepository()
val attachmentRepository = aAttachmentRepository()
+ val baseTemplateRepository = aBaseTemplateRepository()
val docRepo = aDocumentObjectRepository()
val paraStyleRepo = aParaStyleRepository()
@@ -46,6 +48,7 @@ class ReferenceValidatorTest {
displayRuleRepository,
imageRepository,
attachmentRepository,
+ baseTemplateRepository,
)
@Test
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/service/deploy/EvolveDeployClientTest.kt b/migration-library/src/test/kotlin/com/quadient/migration/service/deploy/EvolveDeployClientTest.kt
index 194ee278..85809271 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/service/deploy/EvolveDeployClientTest.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/service/deploy/EvolveDeployClientTest.kt
@@ -332,7 +332,7 @@ class EvolveDeployClientTest {
@Test
fun `uploadDocumentObject for Block uses custom baseTemplate when set on document object`() {
val customBaseTemplate = "icm://Interactive/tenant/BaseTemplates/custom.wfd"
- val block = DocumentObjectBuilder("B1", DocumentObjectType.Block).baseTemplate(customBaseTemplate).build()
+ val block = DocumentObjectBuilder("B1", DocumentObjectType.Block).baseTemplatePath(customBaseTemplate).build()
val targetPath = "icm://Interactive/tenant/B1.jld".toIcmPath()
val draftResult = DraftJsonIpsResult(
draft = CreateDraftResult(guid = draftGuid, url = "http://example.com"),
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/tools/TestObjectBuilders.kt b/migration-library/src/test/kotlin/com/quadient/migration/tools/TestObjectBuilders.kt
index 360122d7..bba9108f 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/tools/TestObjectBuilders.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/tools/TestObjectBuilders.kt
@@ -29,6 +29,7 @@ import com.quadient.migration.api.dto.migrationmodel.TextStyleRef
import com.quadient.migration.api.dto.migrationmodel.Variable
import com.quadient.migration.api.dto.migrationmodel.VariableStructureRef
import com.quadient.migration.api.repository.AttachmentRepository
+import com.quadient.migration.api.repository.BaseTemplateRepository
import com.quadient.migration.api.repository.DisplayRuleRepository
import com.quadient.migration.api.repository.DocumentObjectRepository
import com.quadient.migration.api.repository.ImageRepository
@@ -52,6 +53,7 @@ import com.quadient.migration.shared.DocumentObjectType
import com.quadient.migration.shared.IcmPath
import com.quadient.migration.shared.ImageType
import com.quadient.migration.shared.LineSpacing
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.shared.ParagraphPdfTaggingRule
import com.quadient.migration.shared.Size
import com.quadient.migration.shared.SkipOptions
@@ -92,7 +94,7 @@ fun aBlockDto(
metadata = emptyList(),
skip = SkipOptions(false, null, null),
subject = null,
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { LiteralBaseTemplatePath(it) },
variableStructureRef = variableStructureRef,
)
}
@@ -147,7 +149,7 @@ fun aBlockModel(
created = Clock.System.now(),
lastUpdated = Clock.System.now(),
displayRuleRef = null,
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { LiteralBaseTemplatePath(it) },
options = options,
metadata = emptyList(),
skip = SkipOptions(false, null, null),
@@ -528,3 +530,4 @@ fun aTextStyleRepository() = TextStyleRepository(ProjectName(aProjectConfig().na
fun aDisplayRuleRepository() = DisplayRuleRepository(ProjectName(aProjectConfig().name), statusRepo)
fun aImageRepository() = ImageRepository(ProjectName(aProjectConfig().name), statusRepo)
fun aAttachmentRepository() = AttachmentRepository(ProjectName(aProjectConfig().name), statusRepo)
+fun aBaseTemplateRepository() = BaseTemplateRepository(ProjectName(aProjectConfig().name))
diff --git a/migration-library/src/test/kotlin/com/quadient/migration/tools/model/TestModelObjectBuilders.kt b/migration-library/src/test/kotlin/com/quadient/migration/tools/model/TestModelObjectBuilders.kt
index a5be8190..47c5dcbd 100644
--- a/migration-library/src/test/kotlin/com/quadient/migration/tools/model/TestModelObjectBuilders.kt
+++ b/migration-library/src/test/kotlin/com/quadient/migration/tools/model/TestModelObjectBuilders.kt
@@ -37,6 +37,7 @@ import com.quadient.migration.shared.GroupOp
import com.quadient.migration.shared.IcmPath
import com.quadient.migration.shared.ImageOptions
import com.quadient.migration.shared.ImageType
+import com.quadient.migration.api.dto.migrationmodel.LiteralBaseTemplatePath
import com.quadient.migration.shared.LiteralOrFunctionCall
import com.quadient.migration.shared.MetadataEntry
import com.quadient.migration.shared.Position
@@ -71,7 +72,7 @@ fun aDocObj(
created = null,
lastUpdated = null,
displayRuleRef = displayRuleRef?.let { DisplayRuleRef(it) },
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { LiteralBaseTemplatePath(it) },
variableStructureRef = VariableStructureRef?.let { VariableStructureRef(it) },
options = options,
metadata = metadata,
@@ -108,7 +109,7 @@ fun aBlock(
created = created,
lastUpdated = lastUpdated,
displayRuleRef = displayRuleRef,
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { LiteralBaseTemplatePath(it) },
options = null,
metadata = metadata,
skip = skip,
@@ -140,7 +141,7 @@ fun aTemplate(
customFields = CustomFieldMap(),
created = null,
lastUpdated = null,
- baseTemplate = baseTemplate,
+ baseTemplate = baseTemplate?.let { LiteralBaseTemplatePath(it) },
options = null,
metadata = emptyList(),
skip = SkipOptions(false, null, null),
]