Определение и реализация переменных
При определении переменных контекста ваших устройств/агентов/серверов необходимо задать свойства их определений, т.е. имя, описание, формат, флажки чтения/записи, уровень прав доступа, текст справки и группу. Для объявления новой переменной создайте экземпляр объекта VariableDefinition
и задайте его свойства. Вот пример:
|
После этого добавьте определение переменной к контексту:
Переменные контекста драйвера устройства, соответсвующие настройкам доступа устройства, должны добавляться вызовом
Context.addVariableDefinition()
из методаDeviceDriver.setupDeviceContext()
.Определения переменных контекста драйвера устройства, соответствующие свойствам устройства (переменные настроек устройства), должны возвращаться переопределенным методом
DeviceDriver.readVariableDefinitions()
.Плагины сервера должны добавлять переменные из методов
install()
иstart()
.Агенты на базе Java должны добавлять переменные после создания объекта
Agent
черезAgent.getContext().addVariableDefinition()
.Наконец, скрипты (как скрипты сервера, так и виджета) обычно не должны добавлять никаких переменных.
Для переменных сервера также необходимо задать уровень прав доступа для чтения/записи:
|
Переменные настроек устройства, предоставляемые драйвером устройства, вместе с переменными Agent должны принадлежать группе Группа переменных определяется вызовом |
Переменные, добавляемые вручную (кроме переменных настроек устройства), должны также иметь ненулевой метод чтения, реализующий интерфейс VariableGetter
. Цель метода чтения - обеспечить пользовательский код чтения переменной. Записываемые переменные должны также иметь ненулевой метод установщика, реализующий интерфейс VariableSetter
. Метод установщика должен каким-то образом сохранять новое значение переменной, измененнное системными операторами или различными интсрументами сервера.
Формат таблицы данных, возвращенный методом установщика переменной, должен соответствовать формату, содержащемуся в ее определении. Несоблюдение данного правила приведет к потере данных, поскольку система попытается сконвертировать таблицу данных в формат, предоставленный определением, сохраняя как можно большее количество данных. |
Реализация чтения значения переменной
Этот раздел подробно описывает, как Context
выстраивает и возвращает DataTable
, представляющую значение переменной, когда кто-то вызывает метод getVariable()
.
Вся логика, описанная здесь, реализуется в классе AbstractContext
, включенном в комплект разработчика с открытым исходным кодом.
Чтобы вернуть результирующую DataTable
из метода getVariable()
, AbstractContext
выполняет следующее:
Применяет блокировку чтения переменной для предотвращения одновременных операций чтения. Если любой другой поток читает переменную, текущий поток заблокируется до завершения предыдущей операции чтения.
Проверяет, имеет ли вызывающая сторона (определенная объектом
CallerController
) необходимый эффективный уровень прав доступа в текущем контексте для чтения этой переменной.
Ищет текущий контекст (используя технологию отражения Java) и проверяет его на наличие "метода чтения" со следующей сигнатурой:
public DataTable getV
variable(VariableDefinition def, CallerController caller, RequestController request) throws ContextException
Variable - это имя читаемой переменной.
Если находится метод с такой сигнатурой, он вызывается. Этот метод должен вернуть DataTable
, представляющую значение переменной.
Если "метод чтения" не был найден, наличие
VariableGetter
проверяется вызовомVariableDefinition.getGetter()
. ЕслиVariableGetter
определен (не ноль), вызывается методVariableGetter.get()
. Метод чтения должен вернутьDataTable
, представляющую значение переменной.
Если метод чтения переменной не определен (т.е.
VariableDefinition.getGetter()
возвращает ноль),AbstractContext
вызывает методgetVariableImpl()
. Этот метод может быть переопределен в подклассахAbstractContext
. Если реализация переопределения "понимает" переменную (т.е. "знает" ее имя), она должна вернутьDataTable
, представляющую значение переменной. В других случаях методgetVariableImpl()
должен вернуть ноль.
Если метод
getVariableImpl()
вернул ноль,AbstractContext
вызывает методexecuteDefaultGetter()
. Метод чтения по умолчанию возвращает значение переменной, которая хранилась в базе данных (для кода сервера) или была кэширована в память (для всех других случаев).
Если значение перменной до этого не кэшировалось, метод
executeDefaultGetter()
проверяет, определяется ли значение переменной по умолчанию (ненулевое) вызовомVariableDefinition.getDefaultValue()
. Это значение должно быть ранее задано черезVariableDefinition.setDefaultValue(DataTable value)
.
И, наконец, если значение по умолчанию не определяется в
VariableDefinition
, метод чтения по умолчанию выстраивает и возвращает значение по умолчанию вызовомnew SimpleDataTable(variableDefinition.getFormat(), true)
.
DataTable
, полученная из "метода чтения", методов VariableGetter, getVariableImpl() или метода чтения по умолчанию не сразу возвращается изgetVariable()
. Сначала она проверяется на соответствие формату переменной (доступно черезVariableDefinition.getFormat()
, этот шаг опускается, если возвращается ноль). Если формат таблицы данных соответствует формату, предоставленному определением (или расширяет его, добавляя некоторые поля), эта таблица возвращается в исходном виде. Если формат таблицы не соответствует и не расширяет формат определения,AbstractContext
конвертирует таблицу в "нужный" формат и сохраняет максимальное количество данных. Это делается вызовом методаDataTableReplication.copy()
.
Если коду, реализующему "метод чтения", VariableGetter или getVariableImpl(), нужен доступ к значению переменной, хранящейся в базе данных или памяти, этот код должен напрямую вызывать метод |
Реализация установки значения переменной
Этот раздел подробно описывает, как Context
выстраивает и возвращает DataTable
, представляющую значение переменной, когда кто-то вызывает метод setVariable()
.
Вся логика, описанная здесь, реализуется в классе AbstractContext
, включенном в комплект разработчика с открытым исходным кодом.
Чтобы обработать DataTable
, представляющую новое значение переменной при вызове метода setVariable()
, AbstractContext
выполняет следующее:
Применяет блокировку записи переменной для предотвращения одновременных операций записи. Если любой другой поток записывает переменную, текущий поток заблокируется до завершения предыдущей операции записи.
Проверяет, имеет ли вызывающая сторона (определенная объектом
CallerController
) необходимый эффективный уровень прав доступа в текущем контексте для записи этой переменной.
DataTable
, представляющая новое значение переменной, сначала проверяется на соответствие формату переменной (доступному черезVariableDefinition.getFormat()
, этот шаг опускается, если возвращается ноль). Если формат таблицы данных значения соответствует формату, предоставленному определением (или расширяет его путем добавления полей), эта таблица остается нетронутой. Если формат таблицы значений не соответствует и не расширяет формат определения,AbstractContext
коновертирует таблицу в "нужный" формат и сохраняет максимальное количество данных. Это выполняется вызовом методаDataTableReplication.copy()
.
Если у вызывающей стороны включена проверка уровня прав доступа (т.е. как у обычного системного пользователь), система проверяет, чтобы значения всех полей "только для чтения" в новой таблице были равны значениям соответствующих полей в старой (текущей) таблице, которая внутренне извлекается вызовом
getVariable()
. Значения всех измененных полей "только для чтения" переустанавливаются на те, которые взяты из старой (текущей) таблицы.
Ищет текущий контекст (используя технологию отражения Java) и проверяет его на наличие "метода установщика" со следующей сигнатурой:
public void setV
variable(VariableDefinition def, CallerController caller, RequestController request, DataTable value) throws ContextException
Variable - это имя записываемой переменной.
Если находится метод с такой сигнатурой, он вызывается. Этот метод должен вернуть DataTable
, представляющую новое значение переменной.
Если "метод установщика" не находится, наличие
VariableSetter
проверяется при помощиVariableDefinition.getSetter()
. Если определяетсяVariableSetter
(не ноль), вызывается методVariableSetter.set()
. Метод установщика должен обработатьDataTable
,представляющую новое значение переменной.
Если метод установщика переменной не определен (т.е.
VariableDefinition.getSetter()
возвращает ноль) или метод установщика возвращает false,AbstractContext
вызывает методsetVariableImpl()
. Этот метод может быть переопределен в подклассахAbstractContext
. Если реализация переопределения "понимает" переменную (т.е. "знает" ее имя), она должна обрабатыватьDataTable
, представляющую новое значение переменной и возвращать true. В ином случае методsetVariableImpl()
должен вернуть false.
Если метод
setVariableImpl()
вернул false,AbstractContext
вызывает методexecuteDefaultSetter()
. Метод установщика по умолчанию сохраняет новое значение переменной в базе данных (для кода сервера) или в кэше памяти (для всех других случаев).
Если коду, реализующему "метод установщика", VariableSetter или setVariableImpl(), нужно хранить значение новой переменной в базе данных или памяти, этот код должен напрямую вызывать метод |