How to import models of the same type partly with overwrite enabled and others without?

In our application we have multiple content models. For some of them we only provide the initial content during import and a specific group of users is free to alter them afterwards as they please. We must not import those again at a later time to not loose any edited content. But for other content models we always provide the exact content with more or less frequent updates to those models that need to overwrite the existing ones.

How can we distinguish during data-services init betweens these different kinds of content models so that only the ones we actually want to overwrite are actually overwritten?

As far as I know there is only one phase during init available where we could specify model import paths per mgmtp.a12.dataservices.initialization.import.models.path and there is also only the property mgmtp.a12.dataservices.initialization.import.models.overwrite.models.content available that we could use whether to overwrite none or all content models.

The solution is to create an rpc script that imports the models. In order for this script to work a new rpc operation to update or create a model must be implemented.
The implementation in my case looks like this:

import java.io.IOException;
import java.nio.charset.StandardCharsets;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;

import com.googlecode.jsonrpc4j.JsonRpcParam;
import com.mgmtp.a12.dataservices.exception.ExceptionCodes;
import com.mgmtp.a12.dataservices.model.GenericModel;
import com.mgmtp.a12.dataservices.model.ModelService;
import com.mgmtp.a12.dataservices.rpc.RemoteOperation;
import com.mgmtp.a12.dataservices.rpc.RpcExceptionSupport;
import com.mgmtp.a12.model.header.Header;
import com.mgmtp.a12.model.header.HeaderParseException;
import com.mgmtp.a12.model.header.HeaderParser;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Component
@RemoteOperation(name = "UPDATE_OR_CREATE_MODEL")
@RequiredArgsConstructor
@Slf4j
public class UpdateOrCreateModelOperation {

    private final ResourcePatternResolver resourcePatternResolver;
    private final HeaderParser headerParser;
    private final ModelService modelService;

    public String rpc(@JsonRpcParam("modelUri") String modelUri) {
        Resource resource = resourcePatternResolver.getResource(modelUri);
        if (!resource.exists()) {
            log.error("Could not resolve resource for URI {}.", modelUri);
            throw RpcExceptionSupport.createException(ExceptionCodes.RPC_ERROR_EXCEPTION_CODE, "model.uri.missing",
                    "Resource for model content does not exist.", null,
                    RemoteOperation.RemoteOperationHelper.getOperationId(this.getClass()));
        }
        String modelContent;
        try {
            modelContent = resource.getContentAsString(StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw RpcExceptionSupport.createException(ExceptionCodes.RPC_ERROR_EXCEPTION_CODE, "model.uri.readError",
                    "An error occured while reading data from URI of model.", e.getMessage(),
                    RemoteOperation.RemoteOperationHelper.getOperationId(this.getClass()), e);
        }

        Header header;
        try {
            header = headerParser.parseJson(modelContent);
        } catch (HeaderParseException e) {
            throw RpcExceptionSupport.createException(ExceptionCodes.RPC_ERROR_EXCEPTION_CODE, "model.uri.parseError",
                    "An error occured while parsing the header of the model.", e.getMessage(),
                    RemoteOperation.RemoteOperationHelper.getOperationId(this.getClass()), e);
        }
        GenericModel existingModel = modelService.load(header.getId());

        GenericModel updatedOrCreatedModel;
        try {
            if (existingModel != null) {
                updatedOrCreatedModel = modelService.update(modelContent);
            } else {
                updatedOrCreatedModel = modelService.create(modelContent);
            }
        } catch (RuntimeException e) {
            throw RpcExceptionSupport.createException(ExceptionCodes.RPC_ERROR_EXCEPTION_CODE,
                    "model.uri.updateCreateError", "An error occured while updating or creating the model.",
                    e.getMessage(), RemoteOperation.RemoteOperationHelper.getOperationId(this.getClass()), e);
        }
        return updatedOrCreatedModel.getHeader().getId();
    }
}

The implementation has to decide first whether the model already exists or not in order to either update or create it.

Then the rpc script simply looks something like this:

[
	{
		"jsonrpc": "2.0",
		"method": "UPDATE_OR_CREATE_MODEL",
		"id": "UpdateOrCreateSomeContentModel",
		"params": {
			"modelUri": "classpath:/models/SomeContentModel.json"
		}
	}
]