Set unique document name based on metadata

Each time a new document is uploaded, the Automation action sets a unique document name based in metadata values. 

  • Property okp:data.id stores a unique auto incremental value.
  • Property okp:data.code stores a project code value.
  • Property okp:data.customer stores a customer code.
  • Property okp:data.description stores a document description.
  • When a new document is uploaded the user must fill all the fields except okp:data.id which is automatically set by OpenKM.
  • When Metadata group is changed - event triggered- is executed automation code which generates okp:data.id and renames the document based on mask projectCode-autonumericId-clientCode-description.documentExtension.

The tables used in this sample is defined as:

-- LastID table
create table UNIQUE_ID (UN_ID INT, primary key(UN_ID));

insert into UNIQUE_ID (UN_ID) values (1);


-- Customer table
create table CUSTOMER (CUS_ID varchar(2),CUS_NAME varchar(32), primary key(CUS_ID));


insert into CUSTOMER (CUS_ID, CUS_NAME) values ('01', 'Customer 01');
insert into CUSTOMER (CUS_ID, CUS_NAME) values ('02', 'Customer 02');
insert into CUSTOMER (CUS_ID, CUS_NAME) values ('03', 'Customer 03');

Metadata group definition:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE property-groups PUBLIC "-//OpenKM//DTD Property Groups 3.10//EN"
"http://www.openkm.com/dtd/property-groups-3.10.dtd">
<property-groups>
    <property-group label="Datos" name="okg:data">
        <input label="Id" type="text" name="okp:data.id" width="200px" readonly="true"/>
        <input label="Project code" type="text" name="okp:data.code" width="200px">
            <validator type="req"/>
            <validator type="num"/>
            <validator type="maxlen" parameter="6"/>
            <validator type="minlen" parameter="6"/>
        </input>
        <select label="Customer" name="okp:data.customer" type="simple" 
                optionsQuery="select CUS_ID, CUS_NAME from CUSTOMER order by CUS_NAME">
            <validator type="req"/>
        </select>
        <input label="Description" type="text" name="okp:data.description" width="200px">
            <validator type="req"/>
            <validator type="maxlen" parameter="150"/>
        </input>
  </property-group>
</property-groups>

Automation action:

package com.openkm.plugin.automation.action;

import com.google.gson.Gson;
import com.openkm.core.DatabaseException;
import com.openkm.db.bean.*;
import com.openkm.db.service.LegacySrv;
import com.openkm.module.db.DbDocumentModule;
import com.openkm.plugin.BasePlugin;
import com.openkm.plugin.automation.Action;
import com.openkm.plugin.automation.AutomationException;
import com.openkm.plugin.automation.AutomationUtils;
import com.openkm.util.FileUtils;
import com.openkm.util.PathUtils;
import net.xeoh.plugins.base.annotations.PluginImplementation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@PluginImplementation
public class SetUniqueName extends BasePlugin implements Action {
	private static final Logger log = LoggerFactory.getLogger(SetUniqueName.class);
	private static final String PROPERTY_GROUP_NAME = "okg:data";
	private static final String PROPERTY_FIELD_ID_NAME = "okp:data.id";
	private static final String PROPERTY_FIELD_CODE_NAME = "okp:data.code";
	private static final String PROPERTY_FIELD_CUSTOMER_NAME = "okp:data.customer";
	private static final String CODE_PATTERN = "%06d";


	private static final ArrayList<AutomationRule.EnumEvents> EVENTS_AT_PRE = Stream.of(AutomationRule.EnumEvents.EVENT_PROPERTY_GROUP_ADD).collect(Collectors.toCollection(ArrayList::new));

	private static final ArrayList<AutomationRule.EnumEvents> EVENTS_AT_POST = new ArrayList<>();

	@Autowired
	private AutomationUtils automationUtils;

	@Autowired
	private LegacySrv legacySrv;

	@Autowired
	private DbDocumentModule dbDocumentModule;

	@Override
	public List<AutomationRule.EnumEvents> getValidEventsAtPre() {
		return EVENTS_AT_PRE;
	}

	@Override
	public List<AutomationRule.EnumEvents> getValidEventsAtPost() {
		return EVENTS_AT_POST;
	}

	@Override
	public void executePre(Map<String, Object> env, Object... params) throws AutomationException {
		// Pre stage, here the metadata still has not been created and it is set the unique code in the map of values
		NodeBase node = automationUtils.getNodeBase(env);
		String propertyGroupName = automationUtils.getPropertyGroupName(env);
		try {
			if (node instanceof NodeDocument && PROPERTY_GROUP_NAME.equals(propertyGroupName)) {
				// Set the property in the map of values
				Map<String, String> proceedingProperties = automationUtils.getPropertyGroupProperties(env);
				proceedingProperties.put(PROPERTY_FIELD_ID_NAME, getUniqueCode());
				// Rename document based in metadata values
				String currentName = PathUtils.getName(node.getPath());
				String currentExtension = FileUtils.getFileExtension(currentName); // Extension must not be replaced
				// Getting values
				String id = proceedingProperties.get(PROPERTY_FIELD_ID_NAME);
				String code = proceedingProperties.get(PROPERTY_FIELD_CODE_NAME);
				String jsonValueOfCustomer = proceedingProperties.get(PROPERTY_FIELD_CUSTOMER_NAME);
				Gson gson = new Gson();
				List<String> customerValues = gson.fromJson(jsonValueOfCustomer, List.class);
				String customerValue = customerValues.get(0);
				// Setting the new name
				String newName = code + "-" + id + "-" + customerValue;
				if (!currentExtension.isEmpty()) {
					newName += "." + currentExtension;
				}
				dbDocumentModule.rename(null, node.getUuid(), newName);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new AutomationException(e.getMessage(), e);
		}
	}

	private synchronized String getUniqueCode() throws DatabaseException {
		Integer maxCode = 0;

		StringBuilder query = new StringBuilder("SELECT UN_ID FROM UNIQUE_ID");

		for (List<String> row : legacySrv.executeSQL(query.toString())) {
			maxCode = new Integer(row.get(0));
		}

		// increment value
		legacySrv.executeSQL("UPDATE UNIQUE_ID SET UN_ID = UN_ID +1");

		return String.format(CODE_PATTERN, maxCode);
	}

	@Override
	public void executePost(Map<String, Object> env, Object... params) throws AutomationException {
	}

	@Override
	public String getName() {
		return "Set Unique Name";
	}

	@Override
	public String getParamType00() {
		return Automation.PARAM_TYPE_EMPTY;
	}

	@Override
	public String getParamSrc00() {
		return Automation.PARAM_SOURCE_EMPTY;
	}

	@Override
	public String getParamDesc00() {
		return "";
	}

	@Override
	public String getParamType01() {
		return Automation.PARAM_TYPE_EMPTY;
	}

	@Override
	public String getParamSrc01() {
		return Automation.PARAM_SOURCE_EMPTY;
	}

	@Override
	public String getParamDesc01() {
		return "";
	}

	@Override
	public String getParamType02() {
		return Automation.PARAM_TYPE_EMPTY;
	}

	@Override
	public String getParamSrc02() {
		return Automation.PARAM_SOURCE_EMPTY;
	}

	@Override
	public String getParamDesc02() {
		return "";
	}
}

Create automation rule. Go to Administration > Automation and register a new rule:

  • Rule-based on "add metadata" event at the "pre" stage.
  • Set action named "SetUniqueName" in the actions.
Table of contents [ Hide Show ]