# OpenKM Metadata — Developer Reference

This document covers the OpenKM metadata system: how property groups are defined in XML, the full list of supported field and element types with all their attributes, security and internationalisation support, and how to work with metadata programmatically.

## Related references

When implementing metadata-driven features you will regularly use the OpenKM API and plugin interfaces. Those are documented in the companion reference files listed below. Load them alongside this file for complete context:

- `llms-full-api-*.txt` — OpenKM Java API (OKMPropertyGroup, OKMDocument, OKMFolder, etc.)
- `llms-full-core-utils-*.txt` — Core utility classes
- `llms-full-plugins-*.txt` — Plugin types including form-related plugins (FormValidator, FormInterceptor, OptionSelectValues, etc.)

---

## Metadata

OpenKM organises metadata through **property groups**. A property group is a named collection of typed fields attached to any repository node (document, folder, mail, or record). Groups and their fields are defined in a single XML document managed from the administration panel (**Administration > Repository > Edit metadata**).

### Key concepts

- A **property group** corresponds to a UI tab in the metadata panel.
- Each **field** within a group defines a typed data entry control.
- Groups and fields each have a **name** (system identifier) and a **label** (UI text).
- Naming rules: group names must start with `okg:` and field names must start with `okp:`. Both prefixes are followed by alphanumeric characters and underscores only (`[0-9a-zA-Z_]`). Use `snake_case` rather than `camelCase` to avoid truncation issues on Oracle (32-character column name limit).
- Each group creates two database tables: `OKM_PGRP_CUR_{GROUP}` (current values) and `OKM_PGRP_HIS_{GROUP}` (historical versions). Column names derive from field names with an `RGT_` prefix (e.g. `okp:consulting.return_place` → `RGT_PRO_RETURN_PLACE`).

---

## Metadata XML definition

### DTD version compatibility

The metadata XML format has evolved across OpenKM releases. Always use the DTD that matches (or predates) your installed version. A newer application version supports older DTD versions — backward compatibility is maintained.

| DTD version | Available since | Notes |
|---|---|---|
| `property-groups-3.15.dtd` | 8.2.x | Current version (in-source). Not yet listed on kcenter. |
| `property-groups-3.12.dtd` | 8.1.14 | Last version listed on kcenter. |
| `property-groups-3.11.dtd` | 7.1.41 | Adds HTML support in `<text>` label. |
| `property-groups-3.10.dtd` | 7.1.23 | |
| `property-groups-3.9.dtd` | 7.1.22 | |
| `property-groups-3.8.dtd` | 7.1.9 | |
| `property-groups-3.7.dtd` | 7.1.5 | Earliest version. |

### Document structure

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE property-groups PUBLIC "-//OpenKM//DTD Property Groups 3.15//EN"
                                 "http://www.openkm.com/dtd/property-groups-3.15.dtd">
<property-groups>
  <!-- one or more property-group elements -->
</property-groups>
```

If the OpenKM server has no internet access, use a local DTD reference:

```xml
<!DOCTYPE property-groups PUBLIC "-//OpenKM//DTD Property Groups 3.15//EN"
                                 "file:///home/openkm/property-groups-3.15.dtd">
```

### `<property-group>` attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the tab label in the UI. Supports i18n keys (see Metadata internationalisation). |
| `name` | String | Yes | — | Unique group identifier. Must start with `okg:` followed by `[0-9a-zA-Z_]` only. |
| `visible` | Boolean | No | `true` | Show or hide the entire group in the UI. |
| `readonly` | Boolean | No | `false` | When `true`, prevents modification from the UI; changes via the API are still permitted. |
| `defaultAccess` | Enum | No | `grant` | Group-level default access policy. `grant` = visible to all users; `revoke` = hidden from all users unless explicitly granted. |
| `defaultValueClassName` | String | No | — | Fully-qualified class name of a `FormDefaultValues` plugin that supplies initial field values. |
| `validatorClassName` | String | No | — | Fully-qualified class name of a `FormValidator` plugin that validates the entire group on submit. |
| `autocompleteValueClassName` | String | No | — | Fully-qualified class name of an `AutocompleteFormValues` plugin that provides autocomplete suggestions for the group. |
| `interceptorClassName` | String | No | — | Fully-qualified class name of a `FormInterceptor` plugin that intercepts group-level read and write operations. |

### Database storage

Each property group creates two tables:

| Table | Purpose |
|---|---|
| `OKM_PGRP_CUR_{GROUP}` | Current (latest) metadata values |
| `OKM_PGRP_HIS_{GROUP}` | Historical versions of metadata values |

Column names are derived from field names: the `okp:group.` prefix is stripped, the remaining part is uppercased and prefixed with `RGT_`.
Example: `okp:consulting.return_place` → column `RGT_RETURN_PLACE`.

### Default database column sizes

| Field type | Default `dbColumnSize` |
|---|---|
| Input | 128 |
| Select | 128 |
| SuggestBox | 128 |
| TextArea | 256 |
| CheckBox | 128 |

Override with the `dbColumnSize` attribute on any individual field.

### Complete example

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE property-groups PUBLIC "-//OpenKM//DTD Property Groups 3.15//EN"
                                 "http://www.openkm.com/dtd/property-groups-3.15.dtd">
<property-groups>

  <property-group label="Consulting" name="okg:consulting">
    <input label="Customer" name="okp:consulting.customer" type="text" />
    <input label="Due date" name="okp:consulting.due_date" type="date" />
    <select label="Priority" name="okp:consulting.priority" type="simple">
      <option label="Low"    value="low" />
      <option label="Medium" value="medium" selected="true" />
      <option label="High"   value="high" />
    </select>
    <checkbox label="Reviewed" name="okp:consulting.reviewed" />
    <textarea label="Notes" name="okp:consulting.notes" dbColumnSize="512" />
  </property-group>

</property-groups>
```

---

## Metadata fields

OpenKM supports the following field and element types inside a `<property-group>`:

| Element | Tag | Stores data | Description |
|---|---|---|---|
| Input | `<input>` | Yes | Single-line text, date, link, or folder reference |
| CheckBox | `<checkbox>` | Yes | Boolean (true/false) toggle |
| Select | `<select>` | Yes | Dropdown or multi-select list |
| SuggestBox | `<suggestbox>` | Yes | Autocomplete text field |
| TextArea | `<textarea>` | Yes | Multi-line text or HTML content |
| Text | `<text>` | No | Read-only label or static HTML |
| Separator | `<separator>` | No | Visual divider |
| IFrame | `<iframe>` | No | Embedded web page |
| Script | `<script>` | No | Client-side JavaScript |
| VerticalPanel | `<vpanel>` | No | Vertical layout container |
| HorizontalPanel | `<hpanel>` | No | Horizontal layout container |

Child elements (nest inside a field):

| Element | Tag | Parent(s) | Description |
|---|---|---|---|
| Option | `<option>` | `<select>` | A selectable option within a Select field |
| Validator | `<validator>` | `<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>` | Field-level validation rule |
| Security | `<grantUser>`, `<grantRole>`, `<revokeUser>`, `<revokeRole>` | Any data field | Per-field access control |

---

## Metadata Checkbox field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the field label in the UI. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `value` | Boolean | No | `false` | Initial checked state. Accepted values: `true` or `false`. |
| `width` | String | No | — | HTML element width. Use percentage values (e.g. `50%`) for KCenter UI. |
| `description` | String | No | — | Descriptive text for the field. |
| `readonly` | Boolean | No | `false` | When `true`, prevents modification from the UI. |
| `dbColumnSize` | Integer | No | `128` | Database column size in characters. |
| `defaultAccess` | String | No | `grant` | Default security policy. `grant` = visible to all users; `revoke` = hidden unless explicitly granted. |

### Child elements

`<validator>`, `<grantUser>`, `<grantRole>`, `<revokeUser>`, `<revokeRole>`

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <checkbox label="Reviewed" name="okp:consulting.reviewed" value="false" />
  <checkbox label="Approved" name="okp:consulting.approved" readonly="true" />
</property-group>
```

---

## Metadata IFrame field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the field label in the UI. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `url` | String | Yes | — | URL of the web page to embed. The system automatically appends query parameters: `uuid` (the node UUID) and `propertyGroup` (the group name). Must begin with `http://` or `https://`. |
| `width` | String | No | — | HTML element width. `100%` recommended. |
| `height` | String | No | — | HTML element height (e.g. `300px`). |

### Notes

The IFrame field does not store data. It embeds an external or internal web page inside the metadata panel. The `uuid` and `propertyGroup` query parameters are appended automatically so the embedded page can identify the current node and group context.

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <iframe label="Preview"
          name="okp:consulting.preview"
          url="https://myapp.example.com/metadata-viewer"
          width="100%"
          height="400px" />
</property-group>
```

---

## Metadata Script

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Label for documentation purposes; typically not displayed in the UI. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `source` | String | Yes | — | File name of the JavaScript file to execute. The file must be located in `$CATALINA_HOME/plugins/`. |
| `value` | String | No | — | Optional static value passed to the script at load time. |

### Notes

The Script element injects client-side JavaScript into the metadata form. The script file is loaded from the plugins directory. Form element IDs correspond directly to their `name` attributes; row containers are prefixed with `row-` (e.g. the row wrapping `okp:consulting.input1` has id `row-okp:consulting.input1`).

Use the Script element to implement dynamic field behaviour: showing/hiding fields based on other values, auto-populating fields, or triggering custom validation on the client side.

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <input label="Customer" name="okp:consulting.customer" type="text" />
  <input label="Project"  name="okp:consulting.project"  type="text" />
  <script label="Dynamic logic" name="okp:consulting.script" source="consulting_script.js" />
</property-group>
```

---

## Metadata Select field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the field label in the UI. Supports i18n keys. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `type` | Enum | Yes | — | `simple` — single selection; `multiple` — multiple selections allowed. |
| `width` | String | No | — | HTML element width. Use percentage values for KCenter UI. |
| `height` | String | No | — | HTML element height. |
| `optionsQuery` | String | No* | — | SQL SELECT statement that returns `(id, label)` pairs to populate the option list dynamically. |
| `filterQuery` | String | No** | — | SQL SELECT with a `{0}` placeholder for typed input. Used when `suggestbox="true"` to filter options as the user types. |
| `valueQuery` | String | No** | — | SQL SELECT with a `{0}` placeholder for the stored id. Resolves a saved value back to its display label. Required when `filterQuery` is set. |
| `suggestbox` | Boolean | No | `false` | When `true`, renders the select as an inline suggestbox (filter-as-you-type) instead of a dropdown. Requires `filterQuery`+`valueQuery` or `className`. |
| `filterMinLen` | Integer | No | — | Minimum characters required before filtering activates. Used when `suggestbox="true"`. |
| `className` | String | No* | — | Fully-qualified class name of an `OptionSelectValues` plugin that supplies the option list. |
| `suggestion` | String | No | — | Fully-qualified class name of a `Suggestion` plugin that provides autocomplete suggestions for this field. |
| `parentElement` | String | No | — | Name of another `<select>` field whose selected value is used to filter this field's options (hierarchical selects). |
| `description` | String | No | — | Descriptive text for the field. |
| `readonly` | Boolean | No | `false` | When `true`, prevents modification from the UI. |
| `dbColumnSize` | Integer | No | `128` | Database column size in characters. |
| `defaultAccess` | String | No | `grant` | Default security policy. |

\* `optionsQuery`, `className`, and inline `<option>` elements are mutually exclusive. Use exactly one approach.
\*\* `filterQuery` and `valueQuery` must be specified together; use them when `suggestbox="true"` and not using `className`.

### Child elements

`<option>`, `<validator>`, `<grantUser>`, `<grantRole>`, `<revokeUser>`, `<revokeRole>`

### Examples

**Static options (inline):**

```xml
<select label="Priority" name="okp:consulting.priority" type="simple">
  <option label="Low"    value="low" />
  <option label="Medium" value="medium" selected="true" />
  <option label="High"   value="high" />
</select>
```

**Multiple selection:**

```xml
<select label="Tags" name="okp:consulting.tags" type="multiple">
  <option label="Finance"  value="finance" />
  <option label="Legal"    value="legal" />
  <option label="HR"       value="hr" />
</select>
```

**SQL-driven options:**

```xml
<select label="Country" name="okp:location.country" type="simple"
        optionsQuery="SELECT CT_ID, CT_NAME FROM COUNTRY ORDER BY CT_NAME" />
```

**Plugin-driven options:**

```xml
<select label="Assigned to" name="okp:task.assignee" type="simple"
        className="com.openkm.plugin.form.values.OptionSelectUserList" />
```

**With suggestion plugin:**

```xml
<select label="Keywords" name="okp:consulting.keywords" type="multiple"
        suggestion="com.openkm.plugin.form.suggestion.KeywordSuggestion">
  <option label="Finance" value="finance" />
</select>
```

**Hierarchical (parent-child) selects:**

```xml
<select label="Category" name="okp:consulting.category" type="simple">
  <option value="directives" label="Directives" />
  <option value="handbook"   label="Handbook" />
</select>

<select label="Sub-category" name="okp:consulting.subcategory"
        type="simple" parentElement="okp:consulting.category">
  <option value="benefits" label="Benefits" parentValue="directives" />
  <option value="basic"    label="Basic"    parentValue="handbook" />
</select>
```

---

## Metadata Separator field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown alongside the separator line in the UI. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `width` | String | No | — | HTML element width. Use percentage values for KCenter UI. |

### Notes

The Separator is a visual divider only; it stores no data. Use it to group related fields within a property group for better readability.

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <input label="Customer"  name="okp:consulting.customer"  type="text" />
  <input label="Project"   name="okp:consulting.project"   type="text" />
  <separator label="Approval" name="okp:consulting.sep_approval" />
  <checkbox label="Approved"  name="okp:consulting.approved" />
  <input label="Approved by"  name="okp:consulting.approved_by" type="text" />
</property-group>
```

---

## Metadata SuggestBox field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the field label in the UI. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `filterQuery` | String | No* | — | SQL SELECT with a `{0}` placeholder for the typed input. Returns `(id, label)` pairs for the suggestion list. |
| `valueQuery` | String | No* | — | SQL SELECT with a `{0}` placeholder for the stored id. Returns `(id, label)` to resolve a saved value back to its display label. |
| `className` | String | No* | — | Fully-qualified class name of a `SuggestBoxValues` plugin. |
| `filterMinLen` | Integer | No | — | Minimum number of characters the user must type before the suggestion list appears. |
| `dialogTitle` | String | No | — | Title of the suggestion dialog window. |
| `width` | String | No | — | HTML element width (e.g. `200px` or `50%`). |
| `height` | String | No | — | HTML element height. |
| `description` | String | No | — | Descriptive text for the field. |
| `readonly` | Boolean | No | `false` | When `true`, prevents modification from the UI. |
| `dbColumnSize` | Integer | No | `128` | Database column size in characters. |
| `defaultAccess` | String | No | `grant` | Default security policy. |

\* Either (`filterQuery` + `valueQuery`) together **or** `className` alone is required.

### Child elements

`<validator>`, `<grantUser>`, `<grantRole>`, `<revokeUser>`, `<revokeRole>`

### Examples

**SQL-based suggestbox:**

```xml
<suggestbox label="Country" name="okp:consulting.country"
            filterMinLen="2" dialogTitle="Choose country"
            filterQuery="SELECT CT_ID, CT_NAME FROM COUNTRY WHERE CT_NAME LIKE '%{0}%' ORDER BY CT_NAME"
            valueQuery="SELECT CT_ID, CT_NAME FROM COUNTRY WHERE CT_ID = '{0}'" />
```

**Plugin-based suggestbox:**

```xml
<suggestbox label="Assigned user" name="okp:task.user"
            filterMinLen="1" dialogTitle="Choose user"
            className="com.openkm.plugin.form.values.SuggestBoxUserList" />
```

---

## Metadata Text field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text (or HTML) shown as a static label in the UI. Since v7.1.41, HTML is supported — XML-encode any special characters (e.g. `&amp;`, `&lt;`). |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `width` | String | No | — | HTML element width. Use percentage values for KCenter UI. |
| `height` | String | No | — | HTML element height. |

### Notes

The Text field is a read-only display element; it stores no data. Use it to show instructions, headings, or dynamic HTML inside the metadata form.

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <text label="Please fill in all required fields below."
        name="okp:consulting.instructions" width="100%" />
  <input label="Customer" name="okp:consulting.customer" type="text" />
</property-group>
```

---

## Metadata TextArea field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the field label in the UI. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `type` | Enum | No | — | `text` — plain text; `html` — rich-text HTML editor. |
| `value` | String | No | — | Default content of the field. |
| `placeholder` | String | No | — | Placeholder text shown when the field is empty. |
| `description` | String | No | — | Descriptive text for the field. |
| `width` | String | No | — | HTML element width. Use percentage values for KCenter UI. |
| `height` | String | No | — | HTML element height. |
| `readonly` | Boolean | No | `false` | When `true`, prevents modification from the UI. |
| `dbColumnSize` | Integer | No | `256` | Database column size in characters. |
| `defaultAccess` | String | No | `grant` | Default security policy. |

### Child elements

`<validator>`, `<grantUser>`, `<grantRole>`, `<revokeUser>`, `<revokeRole>`

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <textarea label="Notes"   name="okp:consulting.notes"
            placeholder="Enter any relevant notes here."
            height="150px" dbColumnSize="1024" />
  <textarea label="Summary" name="okp:consulting.summary"
            type="html" height="200px" />
</property-group>
```

---

## Metadata Validator element

A `<validator>` element nests inside a data field and enforces a validation rule when the form is submitted.

### Supported parent fields

`<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`

### Attributes

| Attribute | Type | Required | Description |
|---|---|---|---|
| `type` | String | Yes | Validator type (see table below). |
| `parameter` | String | No | Additional configuration value (e.g. length limit or regex pattern). |

### Built-in validator types

| Type | Parameter | Description |
|---|---|---|
| `req` | — | Field is required (must not be empty). |
| `alpha` | — | Value must contain alphabetic characters only. |
| `alphanum` | — | Value must contain alphanumeric characters only. |
| `dec` | — | Value must be a valid decimal number. |
| `num` | — | Value must be a valid integer. |
| `email` | — | Value must be a valid email address. |
| `url` | — | Value must be a valid URL. |
| `maxlen` | max length | Value length must not exceed the given number of characters. |
| `minlen` | min length | Value length must be at least the given number of characters. |
| `lt` | threshold | Numeric value must be less than the parameter. |
| `gt` | threshold | Numeric value must be greater than the parameter. |
| `min` | minimum | Numeric value must be greater than or equal to the parameter. |
| `max` | maximum | Numeric value must be less than or equal to the parameter. |
| `regexp` | pattern | Value must match the given regular expression. |
| `plugin` | class name | Delegates validation to a `FieldValidator` plugin class. |

### Example

```xml
<input label="Amount" name="okp:invoice.amount" type="text">
  <validator type="req" />
  <validator type="dec" />
  <validator type="gt"  parameter="0" />
  <validator type="max" parameter="999999" />
</input>

<input label="Email" name="okp:contact.email" type="text">
  <validator type="req" />
  <validator type="email" />
</input>

<input label="Code" name="okp:item.code" type="text">
  <validator type="regexp" parameter="[A-Z]{2}[0-9]{4}" />
</input>

<input label="Notes" name="okp:item.notes" type="text">
  <validator type="plugin" parameter="com.example.plugin.MyFieldValidator" />
</input>
```

---

## Metadata Option element

An `<option>` element nests inside a `<select>` field and defines a single selectable item.

### Supported parent fields

`<select>`

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text displayed to the user for this option. Supports i18n keys. |
| `value` | String | Yes | — | Stored identifier. Must be unique within the field. Use only `[a-z_]` (lowercase letters and underscores, no spaces). |
| `parentValue` | String | No | — | When the `<select>` field uses `parentElement`, this ties the option to a specific value of the parent field (hierarchical selects). |
| `selected` | Boolean | No | `false` | Pre-selects this option when the form loads. |
| `cssClass` | String | No | — | Custom CSS class applied to this option's element. |

### Example

```xml
<!-- Flat options with a default selection -->
<select label="Status" name="okp:doc.status" type="simple">
  <option label="Draft"    value="draft"    selected="true" />
  <option label="Review"   value="review" />
  <option label="Approved" value="approved" />
  <option label="Archived" value="archived" />
</select>

<!-- Hierarchical options -->
<select label="Type" name="okp:doc.type" type="simple">
  <option value="contract" label="Contract" />
  <option value="invoice"  label="Invoice" />
</select>

<select label="Sub-type" name="okp:doc.subtype"
        type="simple" parentElement="okp:doc.type">
  <option value="service"  label="Service contract"  parentValue="contract" />
  <option value="purchase" label="Purchase contract"  parentValue="contract" />
  <option value="supplier" label="Supplier invoice"   parentValue="invoice" />
  <option value="customer" label="Customer invoice"   parentValue="invoice" />
</select>
```

---

## Metadata Input field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `label` | String | Yes | — | Text shown as the field label in the UI. Supports i18n keys. |
| `name` | String | Yes | — | Unique field identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `type` | Enum | Yes | — | Field data type. See types table below. |
| `value` | String | No | — | Default value. Dates use the format `yyyyMMddHHmmss`. |
| `width` | String | No | — | HTML element width. Use percentage values for KCenter UI. |
| `height` | String | No | — | HTML element height. |
| `placeholder` | String | No | — | Placeholder text shown when the field is empty. |
| `description` | String | No | — | Descriptive text for the field. |
| `readonly` | Boolean | No | `false` | When `true`, prevents modification from the UI. |
| `timeFormat` | Enum | No | — | For `date` type only: `hm` (hours and minutes), `h` (hours only), `none` (date only). |
| `searchType` | Enum | No | `fuzzy` | Lucene indexing strategy: `fuzzy` (tokenised, full-text searchable) or `exact` (non-tokenised, exact match). |
| `dbColumnSize` | Integer | No | `128` | Database column size in characters. |
| `defaultAccess` | String | No | `grant` | Default security policy. |

### Input types

| Value | Description |
|---|---|
| `text` | Free-text string. |
| `date` | Date (and optionally time) picker. Stored as `yyyyMMddHHmmss`. |
| `link` | Clickable URL stored as text. |
| `folder` | Repository folder path reference. |

### Child elements

`<validator>`, `<grantUser>`, `<grantRole>`, `<revokeUser>`, `<revokeRole>`

### Example

```xml
<property-group label="Contract" name="okg:contract">
  <input label="Reference"   name="okp:contract.reference"   type="text" />
  <input label="Start date"  name="okp:contract.start_date"  type="date" timeFormat="none" />
  <input label="End date"    name="okp:contract.end_date"    type="date" timeFormat="none">
    <validator type="req" />
  </input>
  <input label="Amount"      name="okp:contract.amount"      type="text">
    <validator type="dec" />
    <validator type="gt" parameter="0" />
  </input>
  <input label="Document URL" name="okp:contract.doc_url"   type="link" />
  <input label="Archive folder" name="okp:contract.archive" type="folder" />
</property-group>
```

---

## Metadata VerticalPanel field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `name` | String | Yes | — | Unique container identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `width` | String | No | — | Container width. Use percentage values for KCenter UI. |
| `height` | String | No | — | Container height. |

### Child elements

`<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`, `<text>`, `<separator>`, `<iframe>`, `<vpanel>`, `<hpanel>`.

Note: `<script>` is **not** allowed as a child of `<vpanel>` or `<hpanel>`. Place script elements directly inside `<property-group>`.

### Notes

`<vpanel>` stacks its children vertically. Use it to group related fields or to create multi-column layouts together with `<hpanel>`.

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <vpanel name="okp:consulting.left_col" width="50%">
    <input label="Customer" name="okp:consulting.customer" type="text" />
    <input label="Project"  name="okp:consulting.project"  type="text" />
  </vpanel>
  <vpanel name="okp:consulting.right_col" width="50%">
    <input label="Start date" name="okp:consulting.start_date" type="date" />
    <input label="End date"   name="okp:consulting.end_date"   type="date" />
  </vpanel>
</property-group>
```

---

## Metadata HorizontalPanel field

### Attributes

| Attribute | Type | Required | Default | Description |
|---|---|---|---|---|
| `name` | String | Yes | — | Unique container identifier. Must start with `okp:` and contain only `[0-9a-zA-Z_]`. |
| `width` | String | No | — | Container width. Use percentage values for KCenter UI. |
| `height` | String | No | — | Container height. |

### Child elements

`<input>`, `<checkbox>`, `<select>`, `<suggestbox>`, `<textarea>`, `<text>`, `<separator>`, `<iframe>`, `<vpanel>`, `<hpanel>`.

Note: `<script>` is **not** allowed as a child of `<hpanel>` or `<vpanel>`. Place script elements directly inside `<property-group>`.

### Notes

`<hpanel>` places its children side by side in a row. Combine with `<vpanel>` for complex grid-style layouts.

### Example

```xml
<property-group label="Consulting" name="okg:consulting">
  <hpanel name="okp:consulting.row1">
    <input label="First name" name="okp:consulting.first_name" type="text" width="50%" />
    <input label="Last name"  name="okp:consulting.last_name"  type="text" width="50%" />
  </hpanel>
  <hpanel name="okp:consulting.row2">
    <input label="Email"  name="okp:consulting.email"  type="text" width="50%" />
    <input label="Phone"  name="okp:consulting.phone"  type="text" width="50%" />
  </hpanel>
</property-group>
```

---

## Metadata Security element

Per-field access control overrides the group-level visibility setting. Each data field supports a `defaultAccess` attribute and optional child grant/revoke elements. Revoke always takes priority over grant. Users with `ROLE_ADMIN` always see all fields regardless of security settings.

### Field-level security attributes

| Attribute | Values | Default | Description |
|---|---|---|---|
| `defaultAccess` | `grant` / `revoke` | `grant` | Baseline policy. `grant` = visible to all users; `revoke` = hidden from all users unless explicitly granted. |

### Child security elements

| Element | Attribute | Description |
|---|---|---|
| `<grantUser>` | `name` | Grants access to the named user. |
| `<grantRole>` | `name` | Grants access to all members of the named role. |
| `<revokeUser>` | `name` | Denies access to the named user. |
| `<revokeRole>` | `name` | Denies access to all members of the named role. |

### Precedence rules

1. Revoke always takes priority over grant.
2. `ROLE_ADMIN` members always have access regardless of security settings.
3. When `defaultAccess="revoke"`, all users are denied unless an explicit `<grantUser>` or `<grantRole>` is present.

### Example

```xml
<property-group label="HR Data" name="okg:hr">

  <!-- Visible to everyone (default) -->
  <input label="Employee ID" name="okp:hr.employee_id" type="text" />

  <!-- Only HR role members and the admin user can see this field -->
  <input label="Salary" name="okp:hr.salary" type="text" defaultAccess="revoke">
    <grantRole name="ROLE_HR" />
    <grantUser name="admin" />
  </input>

  <!-- Visible to all except the auditor user -->
  <input label="Notes" name="okp:hr.notes" type="text" defaultAccess="grant">
    <revokeUser name="auditor" />
  </input>

</property-group>
```

---

## Metadata internationalisation

Available since OpenKM v7.1.35. Metadata labels and option texts can be translated into multiple languages using translation keys stored in the `OKM_TRANSLATION` database table.

### How it works

Replace any `label` attribute value with a translation key string. The key must be prefixed with `kcenter.`. OpenKM looks up the key in `OKM_TRANSLATION` for the current user's language and substitutes the translated text. If no translation is found, the key string itself is shown.

### Translation key naming convention

```
kcenter.<scope>.<identifier>
```

Examples:
- Group label: `kcenter.consulting.group`
- Field label: `kcenter.consulting.customer`
- Option label: `kcenter.consulting.priority.high`

### OKM_TRANSLATION table columns

| Column | Description |
|---|---|
| `TR_KEY` | Translation key (e.g. `kcenter.consulting.group`) |
| `TR_LANGUAGE` | Language code (e.g. `en-GB`, `es-ES`, `fr-FR`) |
| `TR_MODULE` | Always `kcenter` |
| `TR_TEXT` | Translated text |

### Example — inserting translations

```sql
-- English
INSERT INTO OKM_TRANSLATION (TR_KEY, TR_LANGUAGE, TR_MODULE, TR_TEXT)
VALUES ('kcenter.consulting.group',    'en-GB', 'kcenter', 'Consulting');
INSERT INTO OKM_TRANSLATION (TR_KEY, TR_LANGUAGE, TR_MODULE, TR_TEXT)
VALUES ('kcenter.consulting.customer', 'en-GB', 'kcenter', 'Customer');
INSERT INTO OKM_TRANSLATION (TR_KEY, TR_LANGUAGE, TR_MODULE, TR_TEXT)
VALUES ('kcenter.consulting.priority', 'en-GB', 'kcenter', 'Priority');

-- Spanish
INSERT INTO OKM_TRANSLATION (TR_KEY, TR_LANGUAGE, TR_MODULE, TR_TEXT)
VALUES ('kcenter.consulting.group',    'es-ES', 'kcenter', 'Consultoría');
INSERT INTO OKM_TRANSLATION (TR_KEY, TR_LANGUAGE, TR_MODULE, TR_TEXT)
VALUES ('kcenter.consulting.customer', 'es-ES', 'kcenter', 'Cliente');
INSERT INTO OKM_TRANSLATION (TR_KEY, TR_LANGUAGE, TR_MODULE, TR_TEXT)
VALUES ('kcenter.consulting.priority', 'es-ES', 'kcenter', 'Prioridad');
```

### Example — metadata XML with i18n keys

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE property-groups PUBLIC "-//OpenKM//DTD Property Groups 3.15//EN"
                                 "http://www.openkm.com/dtd/property-groups-3.15.dtd">
<property-groups>
  <property-group label="kcenter.consulting.group" name="okg:consulting">
    <input label="kcenter.consulting.customer" name="okp:consulting.customer" type="text" />
    <select label="kcenter.consulting.priority" name="okp:consulting.priority" type="simple">
      <option label="kcenter.consulting.priority.low"    value="low" />
      <option label="kcenter.consulting.priority.medium" value="medium" selected="true" />
      <option label="kcenter.consulting.priority.high"   value="high" />
    </select>
  </property-group>
</property-groups>
```
