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:
Take a look at Creating your own 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.