Skip to content

Commit

Permalink
Implement endpoint for document cloning (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
teosarca committed May 29, 2017
1 parent 2c81bb2 commit fbcd877
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ public Document createNewDocument(final DocumentEntityDescriptor parametersDescr
throw new UnsupportedOperationException();
}

@Override
public de.metas.ui.web.window.model.Document createNewDocumentAsCopyFrom(final DocumentEntityDescriptor entityDescriptor, final DocumentId fromDocumentId)
{
throw new UnsupportedOperationException();
}

Document createNewParametersDocument(final DocumentEntityDescriptor parametersDescriptor, final DocumentId adPInstanceId, final IDocumentEvaluatee evalCtx, final IDocumentChangesCollector changesCollector)
{
final IDocumentEvaluatee evalCtxEffective;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -42,6 +43,7 @@
import de.metas.ui.web.session.UserSession;
import de.metas.ui.web.window.datatypes.DocumentPath;
import de.metas.ui.web.window.datatypes.WindowId;
import de.metas.ui.web.window.datatypes.json.JSONCreateDocumentRequest;
import de.metas.ui.web.window.datatypes.json.JSONDocument;
import de.metas.ui.web.window.datatypes.json.JSONDocumentChangedEvent;
import de.metas.ui.web.window.datatypes.json.JSONDocumentLayout;
Expand Down Expand Up @@ -249,6 +251,31 @@ else if (documentPath.isSingleIncludedDocument())
});
}

@PostMapping("/{windowId}")
public JSONDocument createNewDocument(@PathVariable("windowId") final String windowIdStr, @RequestBody final JSONCreateDocumentRequest request)
{
final WindowId windowId = WindowId.fromJson(windowIdStr);

//
// Create new document by copying (including details) from a given template document
// The newly created document is already saved in database.
if (request.getTemplateDocumentId() != null)
{
final DocumentPath fromRootDocumentPath = DocumentPath.rootDocumentPath(windowId, request.getTemplateDocumentId());
final Document newDocument = documentCollection.createRootDocumentAsCopyFromAndCommit(fromRootDocumentPath);
return JSONDocument.ofDocument(newDocument, newJSONOptions().build());
}
//
// Create new document
else
{
final DocumentPath newRootDocumentPath = DocumentPath.newRootDocumentPath(windowId);
return documentCollection.forDocumentWritable(newRootDocumentPath, NullDocumentChangesCollector.instance, document -> {
return JSONDocument.ofDocument(document, newJSONOptions().build());
});
}
}

@PatchMapping("/{windowId}/{documentId}")
public List<JSONDocument> patchRootDocument(
@PathVariable("windowId") final String windowIdStr //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public abstract class DocumentId implements Serializable
{
private static final transient int NEW_ID = -1;
public static final transient String NEW_ID_STRING = "NEW";
private static final transient DocumentId NEW = new IntDocumentId(NEW_ID);
static final transient DocumentId NEW = new IntDocumentId(NEW_ID);

@JsonCreator
public static final DocumentId of(final String idStr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static final DocumentPath rootDocumentPath(final DocumentType documentTyp

return new DocumentPath(documentType, documentTypeId, documentId);
}

public static final List<DocumentPath> rootDocumentPathsList(final WindowId windowId, final String documentIdsListStr)
{
if (documentIdsListStr == null || documentIdsListStr.isEmpty())
Expand All @@ -97,6 +97,11 @@ public static final List<DocumentPath> rootDocumentPathsList(final WindowId wind
.map(documentId -> rootDocumentPath(windowId, documentId))
.collect(GuavaCollectors.toImmutableList());
}

public static final DocumentPath newRootDocumentPath(WindowId windowId)
{
return new DocumentPath(DocumentType.Window, windowId.toDocumentId(), DocumentId.NEW);
}

public static final DocumentPath includedDocumentPath(@NonNull final WindowId windowId, final String idStr, final String detailId, final String rowIdStr)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package de.metas.ui.web.window.datatypes.json;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import de.metas.ui.web.window.datatypes.DocumentId;
import lombok.Data;

/*
* #%L
* metasfresh-webui-api
* %%
* Copyright (C) 2017 metas GmbH
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/

@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
@Data
public class JSONCreateDocumentRequest
{
@JsonProperty("templateDocumentId")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private final DocumentId templateDocumentId;

@JsonCreator
private JSONCreateDocumentRequest(@JsonProperty("templateDocumentId") final DocumentId templateDocumentId)
{
this.templateDocumentId = templateDocumentId;
}
}
6 changes: 5 additions & 1 deletion src/main/java/de/metas/ui/web/window/model/Document.java
Original file line number Diff line number Diff line change
Expand Up @@ -822,9 +822,13 @@ DetailId getDetailId()
return documentPath.getDetailId();
}

/**
* @deprecated Please use {@link Env#getCtx()} or something else
*/
@Deprecated
public Properties getCtx()
{
return Env.getCtx(); // FIXME use document level context
return Env.getCtx();
}

public int getWindowNo()
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/de/metas/ui/web/window/model/DocumentCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,28 @@ private Document createRootDocument(final DocumentPath documentPath, final IDocu
return document;
}

public Document createRootDocumentAsCopyFromAndCommit(final DocumentPath fromRootDocumentPath)
{
if (!fromRootDocumentPath.isRootDocument())
{
throw new InvalidDocumentPathException(fromRootDocumentPath, "root document path was expected");
}
if (fromRootDocumentPath.isNewDocument())
{
throw new InvalidDocumentPathException(fromRootDocumentPath, "existing document path was expected");
}

final WindowId windowId = fromRootDocumentPath.getWindowId();
final DocumentEntityDescriptor entityDescriptor = getDocumentEntityDescriptor(windowId);
assertNewDocumentAllowed(entityDescriptor);

final DocumentsRepository documentsRepository = entityDescriptor.getDataBinding().getDocumentsRepository();
final DocumentId fromDocumentId = fromRootDocumentPath.getDocumentId();
final Document newDocument = documentsRepository.createNewDocumentAsCopyFrom(entityDescriptor, fromDocumentId);
commitRootDocument(newDocument);
return newDocument.copy(CopyMode.CheckInReadonly, NullDocumentChangesCollector.instance);
}

private void assertNewDocumentAllowed(final DocumentEntityDescriptor entityDescriptor)
{
final ILogicExpression allowExpr = entityDescriptor.getAllowCreateNewLogic();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Set;

import org.adempiere.ad.persistence.IModelInternalAccessor;
import org.adempiere.ad.security.TableAccessLevel;
import org.adempiere.ad.wrapper.IInterfaceWrapper;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.model.InterfaceWrapperHelper;
Expand Down Expand Up @@ -388,6 +389,13 @@ else if (methodName.startsWith("is") && (args == null || args.length == 0))
}
}

@Override
public TableAccessLevel getAccessLevel()
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

@Override
public final Object getValue(final String columnName, final Class<?> returnType)
{
Expand Down Expand Up @@ -541,7 +549,7 @@ public final Document getDocument()
{
return document;
}

private final Properties getCtx()
{
return document.getCtx();
Expand Down Expand Up @@ -761,6 +769,27 @@ public boolean isCalculated(final String columnName)
return field != null && field.isCalculated();
}

@Override
public String getDefaultValueLogic(final String columnName)
{
final IDocumentFieldView field = document.getFieldViewOrNull(columnName);
if (field == null)
{
return null;
}

return field.getDescriptor().getDefaultValueExpression()
.map(defaultLogicExpr -> defaultLogicExpr.getExpressionString())
.orElse(null);
}

@Override
public int getDisplayType(final String columnName)
{
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

@Override
public boolean setValueNoCheck(final String columnName, final Object value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ default Document retrieveDocumentById(final DocumentEntityDescriptor entityDescr
*/
Document createNewDocument(DocumentEntityDescriptor entityDescriptor, final Document parentDocument, final IDocumentChangesCollector changesCollector);

Document createNewDocumentAsCopyFrom(DocumentEntityDescriptor entityDescriptor, DocumentId fromDocumentId);

void refresh(Document document);

void save(Document document);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;

Expand All @@ -17,12 +18,15 @@
import org.adempiere.exceptions.DBException;
import org.adempiere.exceptions.DBMoreThenOneRecordsFoundException;
import org.adempiere.model.InterfaceWrapperHelper;
import org.adempiere.model.copyRecord.CopyRecordFactory;
import org.adempiere.model.copyRecord.CopyRecordSupport;
import org.adempiere.util.Check;
import org.adempiere.util.Services;
import org.compiere.model.PO;
import org.compiere.model.POInfo;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.slf4j.Logger;

Expand Down Expand Up @@ -55,7 +59,9 @@
import de.metas.ui.web.window.model.DocumentsRepository;
import de.metas.ui.web.window.model.IDocumentChangesCollector;
import de.metas.ui.web.window.model.IDocumentFieldView;
import de.metas.ui.web.window.model.NullDocumentChangesCollector;
import de.metas.ui.web.window.model.OrderedDocumentsList;
import lombok.NonNull;

/*
* #%L
Expand Down Expand Up @@ -151,7 +157,7 @@ public OrderedDocumentsList retrieveDocuments(final DocumentQuery query, final I
return retriveDocuments(query, limit, changesCollector);
}

public OrderedDocumentsList retriveDocuments(final DocumentQuery query, final int limit, final IDocumentChangesCollector changesCollector)
private OrderedDocumentsList retriveDocuments(final DocumentQuery query, final int limit, final IDocumentChangesCollector changesCollector)
{
logger.debug("Retrieving records: query={}, limit={}", query, limit);

Expand Down Expand Up @@ -297,6 +303,39 @@ public Document createNewDocument(final DocumentEntityDescriptor entityDescripto
.initializeAsNewDocument(documentId, VERSION_DEFAULT);
}

@Override
public Document createNewDocumentAsCopyFrom(@NonNull final DocumentEntityDescriptor entityDescriptor, @NonNull final DocumentId fromDocumentId)
{
assertThisRepository(entityDescriptor);
// TODO: check permissions if we can create a new record

//
// Load the source PO
final SqlDocumentEntityDataBindingDescriptor dataBinding = SqlDocumentEntityDataBindingDescriptor.cast(entityDescriptor.getDataBinding());
final String sqlTableName = dataBinding.getTableName();
final boolean checkCache = false;
final PO fromPO = TableModelLoader.instance.getPO(Env.getCtx(), sqlTableName, fromDocumentId.toInt(), checkCache, ITrx.TRXNAME_ThreadInherited);
if (fromPO == null)
{
throw new DBException("No PO found for " + fromDocumentId);
}

//
// Copy the source PO (and it's children) to "newPO".
final CopyRecordSupport copier = CopyRecordFactory.builder()
.tableName(sqlTableName)
.build().create();

final PO newPO = copier.copyRoot(fromPO, ITrx.TRXNAME_ThreadInherited)
.orElseThrow(() -> new AdempiereException("Copy failed")); // shall not happen

//
// Create the Document from newPO
// FIXME: not efficient, we already have the data loaded into newPO. We shall not go back to database again
final DocumentId newDocumentId = DocumentId.of(newPO.get_ID());
return retrieveDocumentById(entityDescriptor, newDocumentId, NullDocumentChangesCollector.instance);
}

@FunctionalInterface
private static interface FieldValueSupplier
{
Expand Down Expand Up @@ -535,18 +574,19 @@ private PO retrieveOrCreatePO(final Document document)
{
final SqlDocumentEntityDataBindingDescriptor dataBinding = SqlDocumentEntityDataBindingDescriptor.cast(document.getEntityDescriptor().getDataBinding());
final String sqlTableName = dataBinding.getTableName();
final Properties ctx = Env.getCtx();

//
// Load the PO / Create new PO instance
final PO po;
if (document.isNew())
{
po = TableModelLoader.instance.newPO(document.getCtx(), sqlTableName, ITrx.TRXNAME_ThreadInherited);
po = TableModelLoader.instance.newPO(ctx, sqlTableName, ITrx.TRXNAME_ThreadInherited);
}
else
{
final boolean checkCache = false;
po = TableModelLoader.instance.getPO(document.getCtx(), sqlTableName, document.getDocumentIdAsInt(), checkCache, ITrx.TRXNAME_ThreadInherited);
po = TableModelLoader.instance.getPO(ctx, sqlTableName, document.getDocumentIdAsInt(), checkCache, ITrx.TRXNAME_ThreadInherited);

if (po == null)
{
Expand Down

0 comments on commit fbcd877

Please sign in to comment.