Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java V_UNKNOWN "V_UNKNOWN" 233 Только (значение OLE-объекта) Variant Объект определенного Имя класса в символах верхнего регистра пользователем класса или (для объекта из класса EMPOYEE объект встроенного класса возвращается значение "EMPLOYEE") Массив Имя типа массива + круглые скобки, содержащие пробел, в символах верхнего регистра (для массива типа Integer возвращается строка: "INTEGER( )"). Список Имя типа списка + слово "List" в символах верхнего регистра (для списка типа Integer возвращается строка: "STRING LIST"). Пример, Определения типа данных. Dim a As Variant Print Выводит "EMPTY" TypeName(a) a = 1 Print Выводит "INTEGER" TypeName(a) a = "hello" . Print TypeName Выводит "STRING" ( a ) Dim b As String Print TypeName(b$) Выводит "STRING" ' Массивы Dim arrayl (1 To 4} As Long Print TypeName(arrayl&) ' Выводит "LONG( )" Dim arrayV(l To 4) Print TypeName(arrayV) ' Выводит "VARIANT( )" Dim у As Variant ' • у - arrayl Print TypeName (y) ' Выводит "LONG ( )" ' Списки Dim listStr List As String Print TypeName(listStr$) ' Выводит "STRING LIST" Dim listVar List Print TypeName(listVar) ' Выводит "VARIANT LIST" Dim p As Variant p = listStr$ Print. TypeName (p) ' Выводит "STRING LIST" LotusScript классов Class Employee ' определение класса Employee End Class Dim temp As Employee Print. TypeName (temp) Set hire = New Employee Print TypeName(hire) Dim emps(3) As Employee Print. TypeName (emps ()) ' Выводит "EMPLOYEE" ' Выводит "EMPLOYEE" ' Выводит "EMPLOYEE ( )" © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 234 ' Объекты OLE классов Set obj = CreateObject("Word.Application") Print TypeName(obj) ' Выводит "OBJECT" 2.8.3. Операторы и функции обработки строковых данных Оператор Bin Bin[$] ( numExpr) Возвращает двоичное представление числа в строковом виде. Параметр numExpr-числовое выражение. Если значение выражения numExpr имеет дробную часть, то оно округляется до ближайшего целого значения. Значение, возвращаемое оператором Bin, имеет тип Variant DataType 8 (строка), оператор Bin$ возвращает значение типа String. Возвращаемое значение - число в двоичной системе исчисления. Максимальная длина результата - 32 символа. Если тип данных выражения numExpr не Integer и не Long, LotusScript производит попытку привести значение выражения к типу Long. Если подобное преобразование невозможно, выдается ошибка («Overflow»). Пример. ' ' ' .9) ' Выводит "11" Выводит "11" Выводит "11" Выводит "11" (результат вычисления ' выражения - 2,79 - округляется, 'а затем преобразуется) Функция Oct Oct[$] ( numExpr) Возвращает восьмеричное представление числа в строковом виде. Параметр numExpr -числовое выражение. Если numExpr является числом с дробной частью, LotusScript округляет его до ближайшего целого перед преобразованием в восьмеричный вид. Oct возвращает значение типа Variant DataType 8 (строка), a Oct$ возвращает значение типа String. Возвращаемое значение содержит только цифры от 0 до 7 включительно и имеет длину 11 символов. Если тип значения numExpr не Integer или не Long, LotusScript производит попытку преобразовать выражение к типу Long. При невозможности преобразования типа выводится ошибка («Overflow»). Пример. Print Oct$(17) ' Выводит "21" ' Преобразование аргумента из типа Double в тип Long Print Oct$(17.0) ' Выводит "21" ' Округляет аргумент типа Double, а затем преобразует в Long Print Oct$(17.3) ' Выводит "21" 1 Результат вычисления - 16.587 - округляется до 1 7 . 0 и затем преобразуется в Long Print Oct$(17.1 * . 9 7 ) ' Выводит "21" © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 235 Оператор LSet LSet stringVar= stringExpr Присваивает содержимое строки stringExpr строковой переменной stringVar и выравнивает эту строку по левой границе. Параметр stringVar - имя строковой переменной типа String фиксированной или переменной длины, или типа Variant. Если длина stringVar превышает длину stringExpr, то происходит выравнивание по левой границе stringExpr в stringVar и дополняет пробелами справа. Если длина stringVar меньше длины stringExpr, то копируется только возможное количество символов из stringExpr в stringVar. Если stringVar содержит числовое значение, то оно преобразуется в строковое, и далее используется длина уже строкового представления. Если переменная stringVar имеет тип Variant, то она не может иметь значение NULL (в этом случае «емкость» приемника была бы неопределена). Попытка заместить значение NULL вызывает ошибку с кодом 94 -«Invalid use of null». Оператор LSet не может быть использован для операций с переменными типов, определенных пользователем. Иллюстрация работы оператора LSet. Пример. Dim x As Variant x - "qq" LSet x = "abc" Print x LSet x = "с" ' Присвоение символа ' т.к. длина х Print x & "high" х == "с" Print х & "high" Dim someV as Variant Lset someV = "abc" Print someV someV = Null Lset someV = "abc" ' Длина x - 2 ' Присвоение двух левых символов ' Выводит "ab" "с" 2 ' ' ' и дополнение остатка строки пробелами Выводит "с high" Обычное присвоение. Новая длина х - 1 Выводит "chigh" ' Выводит "", т.к. размер значение Empty О ' Ошибка «Invalid use of null» © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 236 Оператор RSet RSet stringVar = stringExpr Присваивает содержимое строки stringExpr строковой переменной stringVar и выравнивает эту строку по правой границе. Использование данного оператора как бы фиксирует емкость переменной-приемника и заполняет её, начиная с правой стороны. Если длина строки stringVar превышает длину строки stringExpr, LotusScript выравнивает вправо строку stringExpr внутри переменной stringVar и добавляет пробелами недостающие символы слева в stringVar. Если длина stringVar меньше длины строки stringExpr, LotusScript копирует только нужное количество символов из строки stringExpr, взятых от ее левой границы, и присваивает значение этой подстроки переменной stringVar. Если stringVar содержит числовое значение, LotusScript сначала преобразует его к с роковому виду, а уже потом устанавливает длину результата. Иллюстрация работы оператора Rset: Длина строкового предст. значения переменной Длина строкового предст. значения переменной Переменная -приемник Переменная -приемник Строка Строка Уместившаяся подстрока Непоместившая ся подстрока Дополняющие пробелы Значение целиком Пример 1, Dun positFin As String * 20 RSet positFin$ = "Right" Print positFin$ ' Строка "Right" выравнена по ' 15 символов строки positFin ' Строка фиксированной длины 20 ' "Right" заведомо короче positFin ' Выводит " Right" правому краю строки positFin и первые являются пробелами Пример 2. ' Выводит "а" Строка "q" присвоена переменной х типа Variant и тем самым установила её длину равной 1. Таким образом, только один символ строки "ab", а именно самый левый - "а", записан в переменную х. Функция Left Left[S] ( expr , n ) Возвращает подстроку, состоящую из первых n символов преобразованного в строку параметра expr. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 237 Параметр expr - числовое выражение или строковое выражение для функции Left; выражение типа Variant или String для функции Left$. Если значение выражения expr является числом, то перед выделением символов 'это число преобразуется в строку. Параметр п - число возвращаемых символов, Функция Left возвращает значение типа Variant DataType 8 (String), а функция Left$ возвращает значение типа String. Если п = 0, то функция возвращает пустую строку ("")• Если n больше, чем длина исходной строки из expr, функции возвращают всю строку. Функция Left(Null,l) возвращает значение Null. Функция Left$(Null,l) выдает ошибку с кодом 94 — «Invalid use of null». Пример. Print Left$("ABC", 2) Print Left$("ABC", 0) Print Left(Null, 2) Dim someV someV = Null Print Left$(someV, 2) ' Выводит "АВ" ' Выводит "" ' Выводит Null Ошибка "Invalid use of null" Функция LeftB Функция LeftB выполняет ту же операцию что и Left. Отличием является то, что LeftB измеряет длину подстроки не в символах, а в байтах. Во внутреннем представлении LotusScript строки кодированы Unicode, где символы кодируются двумя байтами. По этой причине использование функции LeftB может приводить к непредсказуемым результатам. Вместо LeftB следует использовать либо Left, либо LeftB Р. Функция LeftBP LeftBP[$] ( expr , n ) Для указанной строки возвращает подстроку слева из указанного числа байт. Подсчет байт ведется в кодировке текущей платформы. expr - числовое выражение или строковое выражение для функции LeftBP; выражение типа Variant или String для функции LeftBP$. Если значение выражения expr является числом, то перед выделением символов это значение преобразуется в строку. n - длина извлекаемой подстроки в байтах. Функция LeftBP возвращает значение типа Variant DataType 8 (String), а функция LeftBPS возвращает значение типа String. Если n = 0, функция возвращает пустую строку («»). Если n больше, чем длина исходной строки из expr, функции возвращают всю строку. Функция LeftBP(Null) возвращает значение Null. Функция LeftBP$(Null) выдает ошибку с кодом 94 - «Invalid use of null». Функция производит посимвольное выравнивание результата. Это означает, что, если кодировка строки многобайтная и в результат справа попадает не целый код символа, а, например, один байт, то такой символ не включается в результат функции. Пример. Print LeftBP$("ABB", 2) Print LeftBP$("ABB", 0) ' Выводит "АБ" ' Выводит "" © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 238 5 Функция LeftC LeftC ( expr, n ) Используется только для систем письма в колонку (тайская, малайская, арабская, урду, персидская (фарси), лаоская)! Из указанной строки извлекает указанное количество колонок слева. Параметр expr - строковое выражение, содержащее колонки символов. Параметр n - число извлекаемых из исходной строки колонок символов. Если n = 0, функция возвращает пустую строку («»). Если n больше, чем число колонок в исходной строке expr, функции возвращают всю строку. Функция поддерживает следующие системы письма: © Функция StrLeft StrLeft ( stringExpr 1, stringExpr2, [compMethod [, Occurences ]] ) Функция просматривает указанную строку-источник слева направо в поиске подстроки-образца и возвращает подстроку из символов, находящихся слева от найденного образца. Параметр stringExpr1 - строка, в которой производится поиск и выборка (строка-источник). Параметр stringExpr2 — строка, вхождение которой отыскивается в строке-источнике (строка-образец). Параметр compMethod - числовое выражение, задающее правило сравнения строк. Флаг может иметь следующие значения: compMethod Способ сравнения 0 С учетом регистра. С учетом «Pitch» 1 Без учета регистра. С учетом «Pitch» 4 С учетом регистра. Без учета «Pitch» 5 Без учета регистра. Без учета «Pitch» Если аргумент compMethod не указан, то действуют установки оператора Option Compare, если таковой присутствует в текущем модуле. Подробнее о способах сравнения строк см. в описании оператора Option Compare на стр. 163. Использование значения вне этого списка приводит к ошибке с кодом 173 - «Argument out of range». Параметр Occurences — числовое выражение, задающее необходимое число вхождений строки-образца в строке-источнике, которое должно быть достигнуто для получения результата. Значение по умолчанию - 1. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @.-формулы, LotusScript, встроенные классы LotusScript и Java 239 Иллюстрация работы функции StrLeft: Пример, Вызовы функции StrLeft с различными значениями параметров. Const SourceStr$ = "Во поле березка стояла" Print Strleft(SourceStr$, "бере") .. ' Выводит "Во поле " Print Strleft(SourceStr$, "беРе") ' Выводит "" (по умолчанию сравнение идет с учетом регистра) Print Strleft(SourceStr$, "беРе", 0) Print Strleft(SourceStr$, "беРе", 4) ' Выводит "" (явно задано сравнение с учетом регистра) Print Strleft(SourceStr$, "беРе", 1) Print Strleft(SourceStr$, "беРе", 5) ' Выводит "Во поле " (задано сравнение без учета регистра) Print Strleft(SourceStr$, "о", 1, 3) ' Выводит "Во поле березка ст" (все, что до 3-ей буквы "о") Print Strleft(SourceStr$, "о", 1, 4) ' Выводит "" (4-го вхождения не найдено - букв "о" всего 3) Print Strleft(SourceStr$, "") ' Выводит "" (нет строки-образца) © Функция StrLeftBack StrLeftBack ( stringExpr1, stringExpr2, [compMethod [, Occurences ]] ) Функция просматривает указанную строку-источник справа налево в поиске подстроки-образца и возвращает подстроку из символов, находящихся слева от найденного образца. stringExpr1 - строка, в которой производится поиск и выборка (строка-источник). stringExpr2 - строка, вхождение которой отыскивается в строке-источнике (строка-образец). compMethod - числовое выражение, задающее правило сравнения строк. Флаг может иметь следующие значения: compMethod 0 Способ сравнения С учетом регистра. С учетом «Pitch» Без учета регистра. С учетом «Pitch» 4 С учетом регистра. Без учета «Pitch» 5 Без учета регистра. Без учета «Pitch» © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 240 Если аргумент compMethod не указан, то действуют установки оператора Option Compare, если таковой присутствует в текущем модуле. Подробнее о способах сравнения строк см. в описании оператора Option Compare на стр. 163. Использование значения вне этого списка приводит к ошибке с кодом 173 - «Argument out of range». Occurences — числовое выражение, задающее необходимое число вхождений строки-образца в строке-источнике, которое должно быть достигнуто для получения результата. Значение по умолчанию — 1. Иллюстрация работы функции StrLeftBack: Пример. Вызовы функции StrLeftBack с различными значениями параметров. Const SourceStr2$ = "Слово! слово2 словоЗ" Print Strleftback(SourceStr2$, "ло") ' Выводит "Слово! слово2 с" Print Strleftback(SourceStr2$, "Ло") ' Выводит "" (по умолчанию сравнение идет с учетом регистра) Print Strleftback(SourceStr2$, "Ло", 0) Print Strleftback (SourceStr2$, "Ло", 4) 1 Выводит "" (явно задано сравнение с учетом регистра) Print Strleftback(SourceStr2$, "Ло", 1) Print Strleftback(SourceStr2$, "Ло", 5) ' Выводит "Слово! слово2 с" (сравнение без учета регистра) Print Strleftback(SourceStr2$, "Ло", 1, 2) ' Выводит "Слово! с" (искалось второе вхождение справа) Print Strleftback(SourceStr2$, "Ло", 1, 4) ' Выводит "" (вхождений "Ло" всего три) Print Strleftback(SourceStr2$, "") ' Выводит "" (нет строки-образца) Функция Right Right[$] ( expr, n ) Выделяет из преобразованного в строку параметра ехрг заданное количество символов п, начиная с правого конца строки. ехрг - числовое или строковое выражение для функции Right; любое выражение типа Variant или String для функции Right$. Числовое выражение предварительно переводится в строковое. п — числовое выражение - количество выделяемых символов. Функция Right возвращает значение типа Variant DataType 8 (String), функция Right$ -типа String. Если п равно 0, то возвращается пустая строка (""); если п больше, чем количество символов в исходной строке, то возвращается вся исходная строка. Функция Right(Null,l) возвращает значение Null. Функция Right$(Null,l) выдает ошибку с кодом 94 — «Invalid use of null». Пример. Print Right $("ABCDEF", 3) © InterTrust Co. Тел. (095) 9567928 'Выводит "DEF" Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 241 Функция RightB Функция RightB выполняют ту же операцию что и Right. Отличием является то, что RightB измеряет длину подстроки не в символах, а в байтах. Во внутреннем представлении LotusScript строки кодированы Unicode, где символы кодируются двумя байтами. По этой причине использование функции RightB может приводить к непредсказуемым результатам. Вместо RightB следует использовать либо Right, либо RightBP. Функция RightBP RightBP[$] ( expr , n ) Для преобразованного в строку параметра expr возвращает подстроку из указанного числа байт n, начиная с левого конца строки. Подсчет байт ведется в кодировке текущей платформы. expr - числовое выражение или строковое выражение для функции RightBP; выражение типа Variant или String для функции RightBP$. Если значение выражения expr является числом, то перед выделением символов оно преобразуется в строку. n — длина извлекаемой подстроки в байтах. Функция RightBP возвращает значение типа Variant DataType 8 (String), а функция RightBP$ возвращает значение типа String. Если n = 0, то функция возвращает пустую строку (""')• Если n больше, чем длина исходной строки из expr, то функции возвращают всю строку. Функция RightBP(Null, 1) возвращает значение Null. Функция RightBP$(Null, 1) выдает ошибку с кодом 94 - «Invalid use of null». Функция производит посимвольное выравнивание результата. Это означает, что, если кодировка строки многобайтная и в результат справа попадает не целый код символа, а, например, один байт, то такой символ не включается в результат функции. Пример. Print RightBP$("АБВ", 2) Print RightBP$("АБВ", 4) Print RightBP$ ( "АБВ", 0) ' Выводит "БВ" ' Выводит "АБВ" ' Выводит "" © Функция RightC RightC ( expr, n ) Используется только для систем письма в колонку (тайская, малайская, арабская, урду, персидская (фарси), лаоская)! Из указанной строки извлекает указанное количество колонок справа. expr - строковое выражение, содержащее колонки символов. n - число извлекаемых из исходной строки колонок символов.Если n = 0, функция возвращает пустую строку ('"'). Если n больше, чем число колонок в исходной строке expr, то функции возвращают всю строку. © Функция StrRight StrRight ( stringExpr1, stringExpr2, [compMethod [, Occurences ]] ) © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 242 Функция просматривает указанную строку-источник справа налево в поиске подстроки-образца и возвращает подстроку из символов, находящихся справа от найденного образца. stringExpr1 — строка, в которой производится поиск и выборка (строка-источник). stringExpr2 — строка, вхождение которой отыскивается в строке-источнике (строка-образец). compMethod - числовое выражение, задающее правило сравнения строк. Флаг может иметь следующие значения: compMethod Способ сравнения 0 С учетом регистра. С учетом «Pitch» 1 Без учета регистра. С учетом «Pitch» 4 С учетом регистра. Без учета «Pitch» 5 Без учета регистра. Без учета «Pitch» Если параметр compMethod не указан, то действуют установки оператора Option Compare, если таковой присутствует в текущем модуле. Подробнее о способах сравнения строк см, в описании оператора Option Compar . Использование значения вне этого списка приводит к ошибке с кодом 173 - «Argument out of range». Occurences — числовое выражение, задающее необходимое число вхождений строки-образца в строке-источнике, которое должно быть достигнуто для получения результата. Значение по умолчанию — 1. Иллюстрация работы функции StrRight: Пример. Вызовы функции StrRight с различными аргументами. Const SourceStr$ = "Во поле березка стояла" Print Strright(SourceStr$, "бере") ' Выводит "зка стояла" Print Strright (SourceStr$, "беРе") ' Выводит "" (по умолчанию сравнение идет с учетом регистра) Print Strright (SourceStr$, "беРе", 0) Print Strright (SourceStr$, "беРе", 4) " Выводит "" (явно задано сравнение с учетом регистра) Print Strright (SourceStr$, "беРе", 1) Print Strright (SourceStrS, "беРе", 5) ' Выводит "зка стояла" (задано сравнение без учета регистра) Print Strright (SourceStr$, "о", 1, 3} ' Выводит " поле березка стояла" (все, что до 3-ей буквы "о") Print Strright (SourceStr$, "о", 1, 4) ' Выводит "" (4-го вхождения не найдено - букв "о" всего 3) Print Strright (SourceStr$, " " ) ' Выводит "" (нет строки-образца) © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: (@-формулы, LotusScript, встроенные классы LotusScript и Java 243 © Функция StrRightBack StrRightBack ( stringExpr1, stringExpr2, [compMethod [, Occurcnces ]] ) Функция просматривает указанную строку-источник слева направо в поиске подстроки-образца и возвращает подстроку из символов, находящихся справа от найденного образца. stringExpr 1 — строка, в которой производится поиск и выборка (строка-источник). Параметр stringExpr2, - строка, вхождение которой отыскивается в строке-источнике (строка-образец). compMethod - числовое выражение, задающее правило сравнения строк. Это выражение может иметь следующие значения: compMethod Способ сравнения 0 С учетом регистра. С учетом «Pitch» 1 Без учета регистра. С учетом «Pitch» 4 С учетом регистра. Без учета «Pitch» 5 Без учета регистра. Без учета «Pitch» Если аргумент compMethod не указан, то действуют установки оператора Option Compare, если таковой присутствует в текущем модуле. Подробнее о способах сравнения строк см. в описании оператора Option Compare. Использование значения вне этого списка приводит к ошибке с кодом 173 — «Argument out of range». Необязательный параметр Occurences - числовое выражение, задающее необходимое число вхождений строки-образца в строке-источнике, которое должно быть достигнуто для получения результата. Значение по умолчанию - 1. Иллюстрация работы функции StrRightBack: Пример. Вызовы функции StrRightBack с различными значениями параметров. Const SourceStr2$ = "Слово1 слово2 словоЗ" Print Strrightback(SourceStr2$ , "ло") ' Выводит "во1 слово2 словоЗ" Print Strrightback (SourceStr2$, "Лo") ' Выводит "" (по умолчанию сравнение идет с учетом регистра) Print Strrightback(SourceStr2$, "Ло", 0) Print Strrightback (SourceStr2$, "Jlo", 4) ' Выводит "" (явно задано сравнение с учетом регистра) Print Strrightback(SourceStr2$, "Ло", 1) Print Strrightback(Sourcestr2$, "Ло", 5) ' Выводит "во1 слово2 словоЗ" (сравнение без учета регистра) Print Strrightback(SourceStr2$, "Ло", 1, 2) ' Выводит "во2 словоЗ" (искалось второе вхождение справа) Print Strrightback(SourceStr2$, "Ло", 1, 4) © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 244 ' Выводит "" (вхождений "Ло" всего три) Print Strrightback(SourceStr2$, "") ' Выводит "" (нет строки-образца) Функция Len Len ( { stringExpr | variantExpr numericExpr typeName } ) Возвращает количество символов в строке или число байтов, необходимых для хранения числового значения. stringExpr - строковое выражение. Для строкового выражения функция Len возвращает число символов. variantExpr - выражение типа Variant. Для выражения типа Variant функция Len возвращает число символов, содержащихся в значении variantExpr, преобразованном к типу String. numericExpr - имя переменной, элемент массива, элемент списка, элемент типа или класса, определенного пользователем, должен иметь числовой тип данных. В этом случае функция Len возвращает число байт, необходимых для хранения значения выражения numericExpr. typeName - простая переменная, массив, список, экземпляр типа или объект класса, определенного пользователем. В этом случае функция Len возвращает число байтов, содержащихся во всех элементах typeName, кроме элементов типа Variant или типа String переменной длины. Если тип или класс имеет элементы типа Variant или строки переменной длины, то результат функции Len для такой переменной может отличаться от простой суммы размеров элементов. Len(Null) выдает ошибку. Len(v), где v есть Empty, возвращает 0. Если длину строки предпочтительнее вычислить в байтах, а не в символах, используется функция LenB. Функция LenBP используется для вычисления длины строки в байтах в кодировке текущей платформы. Пример 1. Длина строки в символах и числового значения в байтах Dim theString As String theString$ = "alphabet." . -. Print Len(theString$) ' Выводит 8 ' Число байт, необходимых для хранения значения типа Single Dim singleVar As Single Print Len(singleVar!) ' Выводит 4 Пример 2. Тип, определенный пользователем содержит элемент типа String переменной длины. Type Orderlnfo ordID As String * б custName As String End Type Dim ord As Orderlnfo ord.ordID$ = "OR1234" ord.custName$ = "John R. Smith" ' Суммарный размер элементов - 19. Print Len(ord.ordID$) + Len(ord.custName) ' Размер переменной такого типа - 16 Print Len(ord) © InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 245 Функция LenB LenB ( { stringExpr | variantExpr | numericExpr | typeNarne } ) Аналогична функции Len, но всегда возвращает длину строки в байтах. Пример. Длина строки из 8 символов в байтах. Dim theString As String theString$ = "alphabet" Print LenB(theString$) ' Выводит 16 ' Число байт, необходимых для хранения значения типа Single Dim singleVar As Single Print LenB (singleVar!) ' Выводит 4 Следует иметь в виду, что число байт в строке вычисляется по кодировке, используемой LotuScript для внутренней кодировки строк. Этой кодировкой является Unicode. Функция LenBP LenBP ( { stringExpr variantExpr numericExpr | typeName } ) Аналогична функции Len, но возвращает длину строки в байтах. При этом подсчет байт ведется по кодировке текущей платформы. © Функция LenC LenC ( stringExpr) Только для систем письма в колонку (например, тайской)! Возвращает длину строки, измеренную в колонках. stringExpr - строковое выражение, содержащее колонки символов. Результат имеет тип Integer. LenC(Null) выдает ошибку. LenC(v), где v есть Empty, возвращает 0. Оператор Mid Mid[$] ( stringVar, start [, length ]) = stringExpr Замещает часть строки или всю строку символами другой строки. stringVar - переменная типа String или Variant, содержащая строковое значение, не может быть строковым литералом. start - позиция первого символа в stringVar, с которого начинается замена. length - число символов, извлекаемых из stringExpr для вставки. stringExpr - строковое выражение. Символы из stringExpr замещают символы в stringVar. Оператор Mid может изменить размер stringVar в байтах, если, например, stringExpr -строка символов в многобайтовой кодировке (LMBCS), а заменяемые символы строки в stringVar - в однобайтовой. Но длина строки в stringVar, измеренная в символах, всегда остается неизменной. © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 246 Оператор Mid использует из строки stringExpr столько символов, сколько указано параметром length. Если необходимо использовать всю строку stringExpr целиком, то можно указать значение length заведомо превышающее длину stringExpr, Того же результата можно добится просто не указывая аргумента length. Если оказывается, что start + length превышает длину stringVar, то используются не все символы stringExpr, а только необходимые для заполнения в stringVar позиций с start до (start + length - 1). Если номер позиции start превосходит длину строки stringVar, то выдается ошибка с кодом 5 - «Illegal function call». Пример. Dim string1 As.String, string2 As String stringl$ = "ABCDEF" string2$ = "12345" . Mid$(stringl$, 2, 3) = string2$ Print. stringl$ ' Выводит A123EF stringl$ = "ABCDEF" Mid$(stringl$, 2, 10) = string2$ Print stringl$ ' Выводит А12345 stringl$ = "ABCDEF" Mid$(stringl$, 2} = string2$ Print stringl$ ' Выводит А12345 stringl$ = "ABCDEF" . - ' Mid$(stringl$, 7} = string2$ ' Ошибка «Illegal function call» Функция Mid Mid[$] ( expr , start [, length ] ) Возвращает подстроку указанной длины (в символах) из строки с определенной позиции (номер символа). Параметр expr - числовое или строковое выражение. LotusScript преобразует числовое выражение в строковое перед извлечением подстроки. Параметр start -позиция первого символа извлекаемой подстроки, отсчитываемая от первого левого символа исходной строки. Параметр length - число извлекаемых из исходной строки символов. Если аргумент length не указан, то возвращается подстрока строки expr с позиции start до конца строки. Функция Mid возвращает значение типа Variant: DataType 8 (String), а функция Mid$ -типа String. Пример. Print Mid$("ABCDEF", 2, Print Mid$("ABCDEF", 2) 3) ' Выводит BCD ' Выводит BCDEF Оператор и функция MidB Оператор и функция MidB выполняют те же операции что и функция Mid. Отличием является то, что MidB измеряет стартовую позицию и длину подстроки не в символах, а в байтах. Во внутреннем представлении LotusScript строки кодированы Unicode. В Unicode символы кодируются двумя байтами.Таким образом, использование оператора и функции MidB может приводить к непредсказуемым результатам. Вместо MidB следует использовать либо Mid, либо MidBP. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 247 Функция MidBP MidBP[$] ( expr, start [, length ]) Возвращает подстроку указанной длины в байтах из строки, начиная с указанного байта. Подсчет байт ведется в кодировке текущей платформы. expr - числовое или строковое выражение. LotusScript преобразует числовое выражение в строковое перед извлечением подстроки. start - порядковый номер первого байта извлекаемой подстроки, отсчитываемый от начала исходной строки. length - число извлекаемых из исходной строки байт. Если параметр length не указан, то возвращается подстрока строки expr с позиции start до конца строки. Если позиция start превышает длину строки expr, то результатом будет пустая строка. Функция МidBР возвращает значение типа Variant DataType 8 (String), а функция MidBP$ типа String. Функция производит посимвольное выравнивание результата. Это означает, что, если кодировка строки многобайтная и в результат попадает не целый код символа, а, например, один байт, то такой символ не включается в результат функции. Пример. Выводит БВГ Выводит БВГДЕ Выводит >< © Функция MidC MidC ( expr, off [, n ] ) Только для систем письма в колонку (например, тайской)! Из указанной строки извлекает указанное количество колонок, начиная с колонки указанной по счету слева направо. expr - строковое выражение, содержащее колонки символов. off - позиция первой колонки извлекаемой подстроки, отсчитываемая от в исходной строке слева направо. n - число извлекаемых из исходной строки колонок символов. Если указанное смещение off превышает длину строки expr, то результатом функции будет пустая строка. Если n превышает длину остатка строки ехrр с позиции off, либо аргумент n не указан, возвращается весь остаток строки expr с позиции off целиком. Функция InStr InStr ( [ begin , ] string1 , string2 [, compMethod ] ) Возвращает номер позиции первого символа строки, заключенной внутри другой строки. begin - опция, положительное целое числовое выражение. Эта опция определяет позицию внутри строки stringl, начиная с которой функция InStr ищет начало строки string2. Если © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 248 опция begin пропущена, ее значение по умолчанию равно 1 (первый символ — начало строки). Если указан аргумент compMethod, то должна быть указана и опция begin. string 1 - строка, в которой функция InStr ищет строку string2. string2 - строка, которую функция InStr ищет в строке string1. compMethod - числовое выражение, задающее правило сравнения строк. Флаг может иметь следующие значения: compMethod Способ сравнения О С учетом регистра. С учетом «Pitch» 1 Без учета регистра. С учетом «Pitch» 4 С учетом регистра. Без учета «Pitch» 5 Без учета регистра. Без учета «Pitch» Если аргумент compMethod не указан, то действуют установки оператора Option Compare, если таковой присутствует в текущем модуле. Подробнее о способах сравнения строк см. в описании оператора Option Compare на стр. 163. Следующая таблица демонстрирует, каким образом функция InStr реагирует на возможные ситуации. Условие Возвращаемое значение stringl - пустая строка ("") 0 string2 не найдена после начала stringl 0 начало string2 выходит за пределы stringl 0 string2 - пустая строка ("") Значение begin. Если пропущен begin, InStr возвращает значение 1 . Stringl -Null Null string2 -Null Null begin или compMethod - Null Ошибка с кодом 94 — «Invalid use of null» Пример. Значение 5 (позиция первого символа строки LittleString от начала BigString), назначаемое переменной positionOfChar. Dim big As String, little As String Dim positionOfChar As Long big$ = "abcdefghi" little$ = "efg" positionOfChars = InStr(I, big$, little$) Print positionOfChar& ' Выводит 5 © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @,-формулы, LotusScript, встроенные классы LotusScript и Java 249 В случае, если позицию подстроки необходимо получить в байтах, следует воспользоваться функцией InStrB. Функция InStrB InStrB ([ begin , ] stringl , string2 ) Аналогична функции InStr, но в отличие от оной возвращает не позицию символа, а номер байта. При этом используется внутренняя кодировка строки в LotusScript (LotusScript для внутреннего кодирования строк использует Unicode). Функция InStrB не учитывает кодировку текущей платформы. Для этой цели следует использовать функцию InStrBP. Пример. Значение 9 - позиция, которую занимает первый байт littleStr от начала 'bigStr. Dim bigStr As String, littleStr As String Dim positionOfByte As Long bigStr$ - "abcdefghi" littleStr$ = "efg" positionOfByte& = InStrB (1, bigStr$, LittleStr$) Print positionOfByte& ' Выводит 9 Функция InStrBP InStrB ([ begin , ] stringl , string2 ) Аналогична функциям InStr и InStrB, но в отличие от оных возвращает не позицию символа и не номер байта во внутренней кодировке LotusScript, а номер байта в кодировке текущей платформы. Пример. Значение 9 - позиция, которую занимает первый байт littleStr от начала 'bigStr. Dim bigStr As String, littleStr As String Dim positionOfByte As Long , bigStr$ = "abcdefghi" littleStr$ = "efg" positionOfByte& = InStrB (1, bigStr$, Print positionOfByte& ' Выводит 5 . . • ' littleStr$) " '" ' ' ' " © Функция InStrC InStrC ( off, stringl , string2 ) Только для систем письма в колонку (например, тайской)! Для указанной строки возвращает позицию колонки, с которой начинается первое вхождение указанной подстроки. off - положительное целое числовое выражение. Задает номер колонки, с которой начинается поиск. stringl - строковое выражение, содержащее колонки символов; строка, в которой производится поиск. stringl - строковое выражение, содержащее колонки символов; строка, вхождение которой отыскивается. © InterTrust Co. Тел. (095) 9567928 г Язык LotusScript 250 Функция Space Space[$] ( numExpr) Возвращает, строку, содержащую указанное количество пробелов. Параметр numExpr -числовое выражение, задающее необходимое число пробелов. Если оно содержит дробную часть, LotusScript округляет значение выражения до ближайшего целого. Функция Space возвращает значение типа Variant DataType 8 (String), а функция Space$ возвращает значение типа String. Пример. Определяет строку из 4-х пробелов значением переменной smallTab. Выводит Выводит Функция Spc Spc (numExpr) Вставляет указанное количество пробелов в данные, выводимые операторами Print или Print #, начиная с текущей позиции. Параметр numExpr - числовое выражение, значение которого лежит в интервале от 0 до 32000 включительно. Если для файла определена ширина (длина) выводимой строки (см. оператор Width на стр. 306), действие numExpr определяются следующими условиями: • если значение numExpr меньше ширины, LotusScript выводит numExpr пробелов. * если значение numExpr больше ширины, LotusScript выводит допустимое количество пробелов, перенося "остаток" на следующие строки. Если для файла длина выводимой строки не определена, функция Spc выводит все пробелы в одну строку. Пример. Оператор Print # выводит в файл числа. При этом после каждого числа добавляется пробел. Также пробел вставляется перед числом, если оно неотрицательно. Мы намеренно добавляем в конец вывода еще один пробел - Spc(l). Вторая и четвертая строки начинаются с двух пробелов: первый пробел добавлен Spc(I), а второй является лидирующим пробелом перед выводимым числом (3 или 8). Во второй строке число 4 следует за тремя пробелами: первый пробел является концевым для «3», второй вставлен Spc(l), а третий является лидирующим для «4». Open "SPC.TST" For Output As #1 Width #1, 10 For i = 0 To 9 Print #1, i; Spc(1); Next i Close #1 ' Содержимое полученного файла. Конец каждой строки намеренно ' обозначен символом « | » (в файле такого нет) ' 0 1 2 | 3 4 | ' 5 6 7 | 8 9 | InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 251 Функция Str Str[$] (numExpr) Возвращает строковое представление числа. Параметр numExpr - числовое выражение. Функция Str возвращает значение типа Variant DataType 8 (String), а функция Str$ - типа String. Когда LotusScript представляет в виде значения типа String неотрицательное число, впереди добавляется пробел. Пример. Присваивает строковые значения 123 и -123 переменным string1 и string2, соответственно. Для положительного значения добавляется лидирующий пробел. Dim stringl As String, stringl$ = Str$(123) string2$ = Str$(-123) string3$ = Str$(0) Print string2$; stringl$; string2 string3$ As String, string3$ ' Присваивает " 123" ' Присваивает "-123" ' Присваивает " О" ' Выводит: -123 123 0 Функция StrCompare StrCompare ( stringl , string2 [, compMethod ] ) Сравнивает две строки и возвращает результат, stringl и string2 - строковые выражения. compMethod - опция, числовое выражение, задающее правило сравнения строк. Флаг может иметь следующие значения: Способ сравнения compMethod 0 С учетом регистра. С учетом «Pitch» 1 Без учета регистра. С учетом «Pitch» ") 2 Побитно в платформы 4 С учетом регистра. Без учета «Pitch» 5 Без учета регистра. Без учета «Pitch» кодировке текущей Если аргумент compMethod не указан, то действуют установки оператора Option Compare, если таковой присутствует в текущем модуле. Так, например, действие оператора Option Compare Case, NoPitch равносильно значению опции compMethod = 4. Если в текущем модуле нет оператора Option Compare, то по умолчанию действуют настройки «Case» и «Pitch». Подробнее о способах сравнения строк см. в описании оператора Option Compare на стр. 163. Следующая таблица определяет результат действия StrCompare, в зависимости от сравниваемых строк. Аргументы Оба Null stringl меньше string2 Результат сравнения Null _] © InterTrust Co. Тел. (095) 9567928 252 Язык LotusScript stringl равна string2 0 string1 больше string2 1 Пример. Результат получен в ОС Windows 98 Print Print Print Print Print Print Print Strcompare("abc","ab",0)'Выводит Strcompare("ab","abc",0)'Выводит Strcompare("AB","ab",0) 'Выводит Strcompare("AB","ab",1) 'Выводит Strcompare("AB","ab",2) 'Выводит Strcompare("AB","ab",4) 'Выводит Strcompare("AB","ab",5) 'Выводит 1 -1 1 О -1 1 О (abc > ab)(Case Pitch) (ab < abc)(Case Pitch) (AB > ab)(Case Pitch) (идентичны)(NoCase Pitch) (AB < аb(побитно) (AB > ab) (Case NoPitch) (идентичны)(NoCase NoPitch) Функция String String[$] ( stringLen , { charCode stringExpr } ) Возвращает строку, состоящую из символов, определенных указанным кодом в кодировке текущей платформы или первым символом в строке-аргументе. stringLen - числовое выражение, значение которого определяет число символов в возвращаемой строке. Если значение вырадения дробное, LotusScript округляет значение выражения stringLen до ближайшего целого значения. charCode - числовое выражение типа Long, значение которого определяет код символа на используемой платформе. Диапазон допустимых кодов определяется используемой платформой. stringExpr - строковое выражение. Первый символ этой строки "размножается" в возвращаемой строке. Функция String возвращает значение типа Variant DataType 8 (String), а функция String$ -типа String. Пример. Dim stars As String, moreStars As String stars$ = String$(4, Asc ("*")) moreStars$ = String$(8, "* characters") Print stars$, moreStars$ 'Выводит **** ******** Функция LTrim LTrim ( stringExpr ) Удаляет пробелы (если они есть) в начале строки stringExpr и возвращает результат. Функция LTrim возвращает значение типа Variant DataType 8 (String), а функция LTrim$ -типа String. Пример. Dim trimLeft$ As String trimLeft$ = LTrim$(" abc ") Print trimLeft$ Print Len(trimLeft$) ' ' Выводит "abc " (пробел в конце остался) ' Выводит 4 © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 253 Функция RTrim RTrim[S] ( stringExpr ) Удаляет концевые пробелы из строки и возвращает результирующую строку.Параметр stringExpr - выражение типа String. Функция RTrim возвращает значение типа Variant DataType 8 (String), а функция RTrim$ -типа String. Пример, Dim trimRight As String trimRight$ = RTrim$(" abc ") Print trimRight$ ' Выводит " abc" (лидирующие пробелы остались) Print Len(trimRiqht$) ' Выводит 6 Функция Trim Trim[$] ( stringExpr) Удаляет незначащие лидирующие и концевые строки и возвращает результирующую строку, stringExpr - строковое выражение. Возвращаемое значение имеет тип Variant DataType 8 (String), а функция Trim$ - типа String. Функция оставляет пробелы внутри строки. Для их удаления используйте функцию FullTrim. Пример. Dim trimAll As String, testString As String testString$ = " a bc " trimAll$ = Trim$ (testString$ ) Print testString$ 'Выводит " a bc " Print. trimAll$ 'Выводит "a bc" (пробел в середине остался) © Функция FullTrim FullTrim ( expr ) Имеет двойное назначение: из строки удаляет лидирующие, концевые и повторяющиеся внутренние пробелы; из массива удаляет «пустые» элементы. expr - может быть строкой, массивом или выражение типа Variant, содержащим массив или строку. Результат функции имеет тип Variant и содержит строку, если аргумент был строкой, и массив, если аргумент был массивом. Из аргумента-строки удаляются лидирующие, концевые и повторяющиеся внутренние пробелы. Кроме того, из строки удаляются и повторяющиеся внутренние табуляции и переводы строки. Для аргумента-массива функция удаляет «пустые» элементы. То, какой элемент считается «пустым», зависит от типа массива. Так, в ма ссиве строк «пустыми» считаются © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 254 элементы «» (пустая строка). В числовом массиве «пустые» элементы - это нулевые элементы. В массиве типа Variant «пустыми» также считаются элементы со значениями Empty и Null. Очевидно, что после удаления «пустых» элементов размерность результирующего массива может уменьшиться. Если все элементы массива оказались «пустыми», возвращается массив с единственным «пустым» элементом. На момент написания этих строк была доступна только версия Notes 5.O. И в ней, вопреки утверждениям документации, значения элементов массива Empty и Null не считались пустыми и оставлялись функцией FullTrim без изменений. Этот факт иллюстрируется примером на стр. 271. Пример. Удаление пустого пространства в строке ' в середине две табуляции Выводит "abc 123 qwerty" между abc и 123 одна табуляция Функция LCase LCase[$] ( expr ) Возвращает строку, преобразованную к символам нижнего регистра. Параметр expr -числовое или строковое выражение в функции LCase или выражение типа Variant или String в функции LCase$. Функция LCase возвращает значение типа Variant (String), а функция LCase$ возвращает значение типа String. Функция LCase(Null) возвращает Null. Функция LCase$(Null) возвращает ошибку. Пример. ' Выводит Print LCase$("ABC") "abc" Функция UCase UCase[$] (expr) Преобразует любые символы алфавита в символы верхнего регистра и возвращает результирующую строку. expr - для функции UCase, числовое или строковое выражение, для функции UCase$ -выражение, типа Variant или строковое выражение. Функция UCase возвращает значение типа Variant(String), а функция UCase$ - типа String. Функция UCase(Null) возвращает значение Null, функция UCase$(Null) возвращает ошибку. Пример. Заданная строка символов преобразуется к строке символов верхнего регистра. Dim uppercase As String Print UCase$("abc") ' Выводит "ABC" Функция StrConv . . . i ;•••'•• StrConv ( expr , conversionType ) Преобразовывает строку к другому регистру или кодировке. €) InterTrust Co. Тел. (095) 9567928 ..... . . . . .. . • Lotus Domino R. 5: @гформулы, LotusScript, встроенные классы LotusScript и Java 255 expr - строковое или числовое выражение. Числовое выражение преобразуется к строковому виду. conversionType - целое число, определяющее тип преобразования, может принимать следующие значения: Имя константы Значение Тип преобразования SC UpperCase 1 К верхнему регистру SC LowerCase 2 К нижнему регистру SC ProperCase 3 К заглавным буквам SC_Wide 4 Из однобайтной кодировки в двухбайтную SC_Narrow 8 Из двухбайтной кодировки в однобайтную SC_Katakana 16 Из Hiragana в Katakana SC Hiragana 32 Из Katakana в Hiragana Приведенные в таблице константы описаны в файле Isconst.lss. Результат работы функции имеет тип Variant. Если expr есть пустая строка, то результат будет пустой строкой; если expr - Null, то и результат Null. ФУНКЦИЯAsc '• '.' : •: • ' • ' - ' . • ' • :>.•-'•'." ••."•; '.'.-':.- • ; . '''•' i:'-'• ' : ' :':'ул:"-':-'Л' •'.'-:''..':/:";;,;: ; : ,•:-.,.-..:.:::.-.,.-:::-: .;••-:•-.;: :;-:" ;••'-.. Asc ( stringExpr ) Возвращает код (в кодировки текущей платформы) первого символа строки stringExpr. Тип возвращаемого числа - Long. Если значением выражения stringExpr является Null или пустая строка (""), то функция возвращает ошибку. Пример. Dim bigA As Long Dim littleA As Long bigA&. = Asc ("A") littleA& = Asc("a") Print bigA&; littleA& ' Выводит 65 97 ФУНКЦИЯChr Возвращает символ, соответствующей на используемой платформе заданному коду символа. Параметр numExpr - числовое выражение типа Long. Действительным будет только значение, лежащее внутри диапазона значений кодов, представляющих символы на используемой платформе. Функция Chr возвращает результат типа Variant (String). Функция Chr$ возвращает результат типа String. Если значение numExpr является дробным числом, то оно округляется до целого значения. © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 256 Пример. Dim myAlph As String Dim letterCode As Long 'Генерация и конкатенация символов из кодов ASCII For letterCode& = Asc("a") To Asc("z") myAlph$ =- myAlp.h$ & Chr$ (letterCode&} Next Print myAlph$ 'Выводит abcdefghijklmnopqrstuvwxyz Функция UChr l)Chr[$]( longExpr) Возвращает символ, заданный числовым кодом Unicode, Параметр longExpr - выражение, числовое значение которого лежит в диапазоне от 0 до 65535 включительно. Функция UChr возвращает значение типа Variant(String), функция UChr$ возвращает значение типа String. Пример. Dim azAlphabet As String Dim letterCode As Long For letterCode& = Uni("a") To Uni("z") azAlphabet$ = azAlphabet$ + UChr$(letterCode&) Next Print azAlphabet$ 'Выводит abcdefghijklmnopqrstuvwxyz Функция Uni Uni (stringExpr) Возвращает числовой код Unicode для первого символа строки. Параметр stringExpr -строковое выражение. Возвращаемое значение имеет тип Long. Если значением выражения stringExpr является значение Null или пустая строка (""), то функция возвращает ошибку. Пример. Выводит коды Unicode, соответствующие символам А и а. ' Выводит 65 97 Функция UString UString[$] ( stringLen , { charCode | stringExpr } ) Возвращает строку из одинаковых символов. Повторяющийся символ можно определить или числовым кодом или первым символом строки - аргумента. stringLen - числовое выражение, значение которого определяет количество повторяющихся символов в возвращаемой строке. LotusScript округляет значение выражения stringLen до ближайшего целого значения. charCode - числовое выражение, значение которого определяет числовой код повторяющегося символа. Если это необходимо, значение charCode округляется до ближайшего целого значения. Значение кодов Unicode лежат в диапазоне от 0 до 65535 © InterTrust Со. Тел, (095)9567928 Lotus Domino R. 5: (а),-формулы, LotusScript, встроенные классы LotusScript и Java 257 включительно. Если значение выражения charCode меньше 0 или больше 65535, функция возвращает ошибку. stringExpr - строковое выражение. Первый символ этой строки используется, как повторяющийся символ. Функция UString возвращает значение типа Variant(String),. функция UString$ возвращает значение типа String. Пример. Dim stars As String, moreStars As String stars$ = UString$(4, Uni("*")) moreStars$ = UString$(8, "*chars") Print stars$, moreStars$ 'Выводит **** ******** 2.8.4. Операторы и функции обработки данных типа «дата-время» Оператор Time (установить системное время) Time[$] = timeExpr Устанавливает значение системного времени. Параметр timeExpr - выражение, значением которого является дата-время типа String или Variant. Функция NOW - . ... . . . . . . . . . ..;;;: •• • .......................: •; ........... -- •• . . • . . - - - • • „ . • . . . . . . .. -. . . . Now Возвращает текущее системное значение даты-времени. Возвращаемое значение имеет тип Variant DataType7 (Date/Time). . . Значение дата-время представляет собой восьмибайтовое число с плавающей точкой. Целая часть представляет собой порядковый номер текущего дня, считая с 1 января 100 г. н.э. Дробная часть представляет время текущего дня, считая с полночи предыдущего дня. Пример. Вывод на экран текущей даты и времени в формате Long Date. Print Format(Now( ) , "Long Date") 'Выводит Tuesday, June 06, 1995 Функция Date Date[$] Возвращает текущую дату. Возвращаемое функцией Date значение является целой частью значения, возвращаемого функцией Now и имеет тип Variant DataType 7 (Date/Time), а функцией Date$ - типа String. Функция Date эквивалентна функции Today. Пример: Выводится строка "05/25/99" если установлена текущая системная дата 25 мая 1999. Print DateS © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 258 Функция Today Today Возвращает значение системной даты. Тип Variant DataType 7 (Date/Time). Это значение является целой частью выражения, возвращаемого функцией Now. Пример. Значение, возвращаемое функцией Today, присваивается переменной whenNow типа String. Dim whenNow As String whenNow$ = Today() Print whenNow$ 'Выводит 6/7/95 Функция Time Time[$] Функция Time возвращает значение текущего времени. Возвращаемое значение является дробной частью значения, возвращаемого функцией Now. Функция Time возвращает значение типа Variant DataType7 (Date/Time), a Time$ - типа String. Пример. Dim current As String current$ = Time$() Print current$ 'Выводит системное время Функция DateNumber DateNumber ( год, месяц, день ) Возвращает дату, соответствующую указанным году, месяцу и дню. Возвращаемое значение имеет тип Variant DataType7 (Date/Time). год - числовое выражение, определяющее год. месяц - числовое выражение, определяющее месяц года, принимающее значения от 1 до 12 включительно. Если месяц представлен отрицательным значением, функция DateNumber пересчитывает его, вычитая текущее значение из 12 и относит полученное значение месяца к прошедшему году. Например, если год равен 1999, а месяц равен -2, будет получена дата Октябрь. 1998. день - числовое выражение, определяющее день месяца, принимающее значения в диапазоне от 1 до 31. Если значение выражения является отрицательным числом, то функция DateNumber вычисляет значение дня, как разность между максимальным значением дня для предыдущего месяца и этим значением. Например, DateNumber(1995, 5, -3) соответствует дате Апрель, 27, 1995. Пример. Вычисление значения даты с использованием отрицательных аргументов. Print DateNumber(1947, 10, 8) Print DateNumber(95, 2 - 5 , 4 - 10} Print DateNumber( 9 5 , -3, -б) Функция TimeNumber TimeNumber ( hour , minute , second ) © InterTrust Co. Тел. (095) 9567928 х Выводит 10/8/47 ' Выводит 8/25/94 Л Выводит 8/25/94 Язык LotusScript 260 Пример. Dim x As Variant Dim yy As Integer x - DateNumber (1995, 4, 1) yy% = Year(x) Print yy% ' Выводит 1995 Функция Month Month (dateExpr ) Возвращает месяц в виде числа от 1 до 12 для аргумента типа время-дата. Параметр dateExpr - выражение "дата-время" типа String или Variant. Тип данных возвращаемого значения - Variant (Integer). Функция Month(Null) возвращает значение Null. Пример. Dim x As Long Dim mm As Integer . x& = DateNumber(1994, 4, 1) mm% = Month(x&) Print mm% ' Выводит 4 Функция Day Day ( dateExpr ) Возвращает день месяца (целое число от 1 до 31) для аргумента дата-время. Параметр dateExpr - допустимая строка дата-время типа String или типа Variant. Возвращаемое значение имеет тип Variant. (Integer). Значение года, определенное двумя цифрами (см. пример выше) определяется как число из 4 цифр. Функция Day(Null) возвращает значение Null. •* Пример, Dim x As Variant, dd As Integer x = DateNumber(1992, 4, 7) dd% = Day(x) Print dd% ' Выводит 7 Функция Hour Hour ( dateExpr) Возвращает время дня - только час в интервале 0 - 23 - для аргумента дата-время. Параметр dateExpr - допустимая строка, содержащая значение даты-времени типа String или Variant. Возвращаемое значение имеет тип Variant (Integer). Если выражение dateExpr типа Variant содержит значение Null, то функция Hour возвращает значение Null. Пример. Формируется сообщения о текущем времени: часе, минутах и секундах текущего дня. Dim timeFrag As String, hoursFrag As String © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные массы LotusScript и Java Dim minutesFrag As String, secondsFrag As Dim crlf As String, message As String timeFrag$ = Format(Time, "h:mm:ss AM/PM") hoursFrag$ = Str( 2 3 - Hour(Time)) minutesFrag$ = Str(59 - Minute(Time)) secondsFrag$ = Str( 6 0 - Second(Time)) crlf$ = Chr(13) & Chr(lO) 261 String message$ = "Current time: " & timeFrag$ & ". " & crlf$ & "Time remaining in the day: " & hoursFrag$ & " hours, " & minutesFragS & " minutes, and " & secondsFrag$ & " seconds." MessageBox(message$) Функция Minute Minute ( dateExpr ) Возвращает значение минут (целое число от 0 до 59) для аргумента дата-время. Параметр dateExpr - выражение, содержащее значение даты/времени, тина String или Variant. Тип возвращаемого значения - Variant (Integer). Функция Minute(Null) возвращает значение Null. Пример. Формируется сообщение о значении текущего времени в виде чисел, представляющих час, минуту и секунду текущего дня Dim timeFrag As String, hoursFrag As String Dim minutesFrag As String, secondsFrag As String Dim crlf As String, message As String timeFrag$ = Format (Time, "h:mm:ss AM/PM") hoursFrag$ = Str(23 - Hour(Time)) minutesFrag$ = Str( 5 9 - Minute(Time)) . secondsFrag$ =- Str(60 - Second (Time) ) crlf$ = Chr(13) & Chr(10) message? = "Current time: " & timeFrag$ & ". " & crlf$ & "Time remaining in the day: " _ & hoursFrag$ & " hours, " & minutesFrag$ & " minutes, and " _ & secondsFrag$ & " seconds." MessageBox(message$) Функция Second Second (dateExpr) Возвращает секунды (целое значение от 0 до 59) для аргумента дата-время. Параметр dateExpr - строка дата-время типа String или Variant. Возвращаемое значение имеет тип Variant (Integer). Функция Second(Null) возвращает значение "Null. Пример. Формируется и выводится сообщение о значении текущего времени. Dim timeFrag As String, hoursFrag As String Dim minutesFrag As String, secondsFrag As Dim crlf As String, message As String timeFrag$ = Format(Time, "h:mm:ss AM/PM") hoursFrag$ = Str( 2 3 - Hour(Time)) minutesFrag$ = Str(59 - Minute (Time) ) String . © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 262 secondsFrag$ - Str(60 - Second(Time)) crlf$ = Chr(13) & Chr(lO) message$ = "Current time: " & timeFrags$ & ". message$ = "Current time: " & timeFrag$ & ". " & crlf$ & "Time remaining in the day: " & hoursFrag$ & " hours, " & minutesFrag$ & " minutes, arid " & secondsFrag$ & " seconds." MessageBox(message$) Функция Timer Timer Возвращает время в секундах от полуночи до текущего момента. Возвращаемое значение имеет тип Single. Пример. Определяется длительность выполнения цикла из 10 000 итераций. Dim startTime As Single Dim elapsedTime As Single . startTime! = Timer(} For counter% = 1 To 10000 Next counter! elapsedTime! = Timer() - startTime! Print "10000 iterations in "; elapsedTime; " seconds" Функция Weekday Weekday ( dateExpr) Возвращает номер дня недели (в интервале от 1 до 7) для аргумента типа дата-время. Параметр dateExpr - значение даты-времени типа String или Variant DataType7 (Date/Time). Тип возвращаемого значения - Variant (Integer). Первым днем недели считается воскресенье, вторым - понедельник, и т.д. Функция Weekday(NulI) возвращает значение Null. Пример. Dim x = wd% Print x As Variant, wd As Integer DateNumber(1993, 7, 7) = Weekday(x) wd% 'Выводит: 4 2.8.5. Форматирование данных (функция Format) Format[$] ( expr [, fmt ] ) Форматирует число, значение дата-время или строку, для которых возможна эта. операция. Параметр expr - любое выражение, которое оценивается: • как числовое, если fmt имеет числовой формат; • как дата-время, если fmt имеет формат даты-времени; • как строка, если fmt имеет формат строки. fmt - опция, являющаяся строкой форматирования, которая может быть: • строкой, содержащей имя предварительно определенного формата; • строкой символов формата. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @~формулы, LotusScript, встроенные классы LotusScript и Java 263 Если строка fmt не является строкой формата, то функция FormatS выполняется, как функция Str[$]. Функция Format возвращает строку типа Variant, а функция FormatS возвращает строку типа String. Если значением выражения ехрг является строка и значением опции fmt - число в строковом формате, то предпринимается попытка преобразовать строку в число. При успешном выполнении этой операции результат форматируется. Если строка преобразуется в число, то предпринимается попытка преобразовать строку в формат даты-времени и в число. В случае успешного выполнения этих преобразований результат форматируется. Если значением выражения ехрг является число, го можно использовать одно из имен форматов, представленных ниже, или создать свой числовой формат, использующий числовые коды форматирования. Имя числового формата Отображаемое значение для ехрг с разделением тысяч General Number Отображение, использующее системные назначения ОС. В OS/2, функция не будет добавлять знак $ к числу Currency Fixed Наименьшее значение изображается с одним знаком слева от десятичного разделителя, и двумя знаками справа Standard С разделителем тысяч Percent Значение ехрг в интервале от 0 до 100, с добавлением (%) после числа Scientific. Научное представление (в экспоненциальной форме) с добавлением в конце символа Е и показателя степени со знаком Yes/No No, если число равно 0, в противном случае - Yes False, если число равно 0, в противном случае - True Off, если число равно 0, в противном случае - On On/Off. Коды числового форматирования Следующая таблица форматирования. Код представляет символы, используемые для числового Значение "" (Empty) Вывод не форматированного числа 0 (ноль) Специальный цифровой режим. Выводит нуль для любой незначащей цифры в формате, показывая все значащие цифры слева и справа от разделителя целой и дробной части. Если количество цифр в числе превышает определенное в формате, число округляется до ближайшего подходящего значения. # (знак фунта) Условное цифровое отображение. Соответствует использованию 0 с исключением значащих цифр справа и слева от десятичного разделителя. . (точка) Десятичный разделитель. Позиция десятичного разделителя в формате. Если форматный код включает в себя 0 непосредственно слева от десятичного разделителя, а число между ними -1 и с 1 начинается © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 264 отделяемая часть, то будет использовано положение десятичного разделителя определенное используемой операционной платформой. % (процент) Процентная величина. Определяет число, значение которого не превышает 100, имеющее в последней позиции знак %. , (запятая) Разделитель тысяч. Разделяет число на группы по три значащих цифры, начиная с первой после десятичного разделителя. - + () Буквенные символы. Показываются в числе, если они использованы в строке форматирования. \ Буквенная приставка. Обеспечивает отображение следующего за ней символа, например \# отображает #. Для отображения самого знака \ используется \\. "ABC" Литеральная строка, заключенная в кавычки. Для спецификации значения кавычек используется Chr(34). Символы, заключенные в кавычки определяют символы, отображаемые форматной строкой. Разделяет секции формата - положительную, отрицательную, нулевую 0 и Null-секцию. Если пропущена отрицательная или 0 секция, но присутствуют разделители этих секций, форматирование происходит также, как и при их наличии. Строка форматирования может содержать в себе от одной до четырех секций, разделенных знаком точка с запятой ( ; ). При наличии в формате более одной секции, секции, следующие за первой определяют форматирование других значений числового выражения. Следующая таблица определяет использование секций в одно - и многосекционной строке форматирования. Секции Описание Одна Формат, используемый для всех чисел Две Первая секция форматирует положительные числа и 0. Три Четыре Вторая секция форматирует отрицательные числа Первая секция форматирует положительные числа. Вторая секция форматирует отрицательные числа. Третья секция форматирует 0. Первая секция форматирует положительные числа. Вторая секция форматирует отрицательные числа. Третья секция форматирует 0. Четвертая секция форматирует Null. Форматирование данных дата-время Т.к. -значение дата-время имеет внутреннее представление в виде числа с плавающей точкой, то это значение может форматироваться, как число, или как дата-время. Возможное использование любого из указанных форматов, или формата, созданного пользователем, представлено в следующей секции. Представление переменной дата-время Название формата дата-время Общий формат- Стандартный формат. Преобразуется в формат числа с плавающей точкой дата-время. Если число имеет дробную часть, то представляется только дата. Если число не имеет целой части, © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (a-формулы, LotusScript, встроенные классы LotusScript и Java 265 Long Date представляется только время . Long Date определяется используемой ОС в рамках международного стандарта. Medium Date dd-mmm-yy (yy/mmm/dd в Японии) Short Date Short Date определяется используемой ОС в рамках международного стандарта. Long Time Long Time определяется используемой ОС в рамках международного стандарта. Long Time всегда показывает текущее значение времени (час, минута, секунда). Medium Time Часы (0 - 12) и минуты, использующие разделитель для дата-время и описание АМ/РМ (АМРМ в Японии) Short Time Часы (0 - 23) и минуты, используется только разделитель дата-время. Коды форматирования данных дата-время Следующая таблица описывает символы, которые могут использоваться в форматах, созданных для представления значений дата-время. Код Значение: / Разделитель времени. Разделяет часы, минуты, секунды в формате значения времени. Разделитель даты. Разделяет день, месяц и год в формате значения даты. с Представляет дату в виде ddddd, и время в виде ttttt (см. ниже). у Номер дня в годе (1 - 366). d День в месяце (1 -31). dd День в месяце (0 ! -31). Odd Сокращенное название дня недели (Sun - Sat). dddd Промежуток времени между днями недели (Sunday - Saturday). Ddddd Положение цифр в дате (день, месяц, год) в международном формате строка Short Date. В противном случае, по умолчанию используется формат mm/dd/yy. Dddddd Положение цифр в дате (день, месяц, год)в международном формате строка Short Date. В противном случае, по умолчанию используется формат mmmm dd, yyyy. \v Номер дня недели (1 - 7). Воскресенье - 1 . vvw Номер недели в году (1 - 53). m Номер месяца в году (1 - 12). Если в этом формате присутствует символ h минуты представляются в диапазоне 0 - 59. mm Mmm Номер месяца в году в виде (01 - 12). Если в этом формате присутствует символ h минуты представляются в диапазоне 00 - 59. Сокращенное 3-х символьное название месяца (Jan - Dec). mtnmm Промежуток времени между месяцами года (January - December), q Номер квартала в году (1 - 4). УУ Две последние цифры года (00 - 99). : ) InterTrust Co. Тел. (095) 9567928 Язык LotusScript 266 Yyyy Полное значение года (0100 - 9999). h Значение часа дня в виде (0 - 23). hh Значение часа дня в виде (00 - 23). n Значение минуты в часе в виде (0 - 59). nn Значение минуты в часе в виде (00 - 59). s Значение секунды в минуте в виде (0 - 59). ss Значение секунды в минуте в виде ((00 - 59). Ttttt Значение времени, включающее значения часа, минут, секунд, использующее разделитель, предусмотренный используемой ОС. Если используется дополняющее значение 0 (01), предусмотренное в системе, то время имеет формат 10:00 AM или РМ. По умолчанию формат времени имеет вид h:mm:ss. AМ/РМ Используется часовой интервал от 1 до 12, с указанием AM или am/pm PM в зависимости от половины дня (до и после полудня). Используется часовой интервал от 1 до 12, с указанием А или Р в зависимости от половины дня (до и после полудня). Используются значения часа дня в интервале от 1 до 12. В файле WIN. INI время содержится в виде строки 1 159 для дополуденных значений часа, и в виде 2359 для послеполуденных. Для АМРМ не имеет значения используемый регистр клавиатуры. По умолчанию используется представление АМ/РМ. A/P a/p AMPM Следующая таблица демонстрирует использование форматирования даты/времени для даты 12 апреля 1995 г. и времени 6:43:04: Формат Представление m/d/yy 4/12/95 d-mmm-yy 12-Apr-95 d-mmmm 12-April mmmm-yy April-95 У 102 hh:mm AM/PM 06:43 PM h:mm:ss a/p 6:43 :04p h:mm 18:43 h:mm:ss 18:43:04 m/d/yy h:mm 4/12/95 18:43 Коды форматирования строковых данных Форматировать строку можно с помощью функций Format или Format$, использующих коды форматирования. Строка форматирования может состоять из одной или двух секций, разделенных знаком (;). Односекционный формат воздействует на все стро ки, в двухсекционном, первая секция воздействует на не пустую строку, а вторая на строку со значением Null или (""). Следующая таблица определяет символы, использующихся при создании формата для строки. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (формулы, LotusScript, встроенные классы LotusScript и Java 267 Код Значение @ Представление данного символа. Если строка формата включает в себя этот символ, то он выводится в соответствующую позицию, иначе выводится пробел. При наличии (@) формат должен содержать знак (!). & Опция представления символа. Если строка формата включает в себя этот символ, то он выводится в соответствующую позицию. В противном случае ничего не выводится. При наличии (&) формат должен содержать знак (!). < Все символы форматируемой строки, соответствующие нижнему регистру. > Все символы форматируемой строки, соответствующие верхнему регистру. i Заполнение символами @ или & слева направо Пример. Dim rev As Currency, expense As Currency, bal As Currency rev@ = CCur(InputBox("How much did we make this month?"}) expenses = CCur(InputBox("How much did we spend?")) bal@ = rev@ - expensed MessageBox "Our balance this month is " & Format(bal@, "Currency") 2.8.6. Функции работы с массивами ОператорOptionBase Option Base base Оператор устанавливает нижнюю границу по умолчанию для всех измерений массивов в значение base (0 или 1). По умолчанию нижняя граница измерений массивов установлена в 0. Option Base действует в пределах, содержащего его модуля и может использоваться в модуле только один раз. Если он используется, то должен предшествовать объявлениям всех массивов и операторам ReDim в этом модуле. Пример. Создание одномерного массива из 20 элементов (sample(l) - sample(20)) с начальным значением индекса равным 1. Option Base I Dim sample (20) As Integer . ФункцияLBound LBound ( arrayName [, dimension ] ) Возвращает значение нижней границы указанного измерения массива. arrayName - имя массива. Параметр dimension - опция, целое число, определяющее измерение массива, значение нижней границы которого необходимо получить. Возвращаемое значение имеет тип Integer. По умолчанию нижняя граница размерности массива есть 0 или 1, что определяется назначениями в Option Base (см. описание опции Option Base на стр. 149). Пример. Dim minima(10 То 20) Print LBound(minima) ' Выводит: 10 © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 268 Функция UBound i; UBound ( arrayName [, dimension ]) " Возвращает значение верхней границы указанного измерения dimension массива arrayName. Возвращаемое значение имеет тип Integer. Пример. Dim maxima(10 То 20) Dim upperBound As Integer . upperBound% = UBound(maxima) Print upperBound% 'Выводит: 20 - . .. © Функция ArrayAppend • ..::-:: :::;;>,- ... .......... .•--'":...-.. ... ..;..•>•; • -•-•;.... -:. ArrayAppend (array], v2 ) Добавляет массив к другому массиву. Если вы уже знакомы с языком @-формул Notes, то функцию ArrayAppend удобно понимать как аналог оператора «:». Аргументы: array! - значение типа Variant, содержащее массив. v2 - произвольное значение типа Variant. Возвращаемый результат является значением типа Variant, содержащим массив. Данный массив обладает следующими свойствами: • размерность получаемого массива равна сумме размерностей аргументов (если v2 скалярное значение, то оно рассматривается как одноэлементный массив); * если объединяются массивы одинаковых типов, то результирующий массив получается того же типа; • если объединяются массивы разных типов, то результирующий массив содержит значения типа Variant, но реальные типы элементов совпадают с типами соответствующих элементов исходных массивов; * нижнее значение измерения совпадает с оным в vl Функция не затрагивает оригинальных значений аргументов — vl и v2. Притом, что второй аргумент - v2 - может быть скалярным значением или одномерным массивом, первый аргумент обязан быть одномерным массивом. В противном случае возникает ошибка времени исполнения «Type Mismatch». Превышение максимально допустимой размерности массива также приводит к ошибке времени исполнения - «Subscript out of range». Пример 1. Объединение двух массивов различных типов. Dim vl(2) As Integer Dim v2( 1 ) As String Dim v3 As Variant Dim i% . vl ( 0 ) = 1 v l ( l ) =2 vl( 2 ) = 3 v2( 0 ) - "4" v 2 ( l ) = "5" v3 -- Arrayappend (vl, v2) For i% = Lbound(v3) To Ubound(v3) © InterTrust Co. Ten. (095) 9567928 • .- • - Lotus Domino R. 5: (а^формулы, LotusScript, встроенные классы LotusScript и Java 269 Print i%, Typename(v3(i%}) Next ' Вывод в строке состояния: х 1 INTEGER v 2 INTEGER ' 3 INTEGER 1 4 STRING ' 5 STRING © Функция ArrayGetlndex ArrayGetlndex ( arrayName, value [, optCompare] ) Возвращает позицию значения value в массиве arrayName. Если вы уже знакомы с языком @-формул Notes, то функцию ArrayGetlndex удобно понимать как аналог функции @Member. Аргументы: arrayName — массив или значение типа Variant, содержащее массив value - произвольное значение optCompare - числовая опция, задающая правила сравнения значений. Если искомое значение присутствует в массиве, то результатом является значение Variant типа Long, содержащее номер позиции искомого значения в массиве. Е.СЛИ значение value не содержится в массиве аrr, то возвращается NULL. При выполнении сравнения и элементы массива АДГ и значение value значения предварительно преобразуются к строковому виду. Те элементы, преобразование которых в строковом виде невозможно, в сравнении не участвуют. В случае если массив АДГ имеет несколько измерений, позиция элемента определяется по следующему правилу. Массив виртуально представляется имеющим одно измерение с размерностью равной сумме размерностей всех его измерений. Индекс представляется состоящим из нескольких частей - по числу измерений оригинального массива. «Быстрее» изменяется первая часть индекса, соответствующая первому измерению. Данное правило иллюстрирует пример 2. Опция optCompare является числом 0, 1 , 4 или 5. Определение этих значений аналогично определению для функции InStr (см. описание функции InStr на стр. 247). В случае если опция пропущена, используется значение по умолчанию, определяемое наличием или отсутствием для текущего модуля опции Option Compare (стр. 163). Пример 1. Использование функции ArrayGetlndex Dim arr{2) As Integer arr(O) - 1 arr(l) = 3 arr(2) = 4 Print. Arraygetindex(arr, 1), Arraygetindex(arr, "4"), Arraygetindex(arr, 8) ' Вывод в строке состояния ' 0 2 Null Пример 2. Случай массива с несколькими измерениями Dim arr(l, 1) As Variant © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 270 H arr(0, 0) - "1" arrfl, 0) = "3" arr (0, 1) = "4" arr(l, 1) = "7" Print Arraygetindex (arr, "1"), Arraygetiridex (arr, "4"), Arraygetindex(arr, "8") ' Вывод в строке состояния ' 0 2. Null .•;;.V © Функция ArrayReplace ArrayReplace ( arrayName, v2, v3) Функция возвращает копию массива arrayName, в котором элементы, имеющие аналоги в v2. заменяются на соответствующие элементы v3. Если вы уже знакомы с языком @-формул Notes, то функцию ArrayReplace удобно понимать как аналог функции @Replace. arrayName - значение типа Variant, содержащее массив. v2, v3 — значения типа Variant, содержащие массивы; могут быть скалярными значениями тогда они понимаются как массив размерности 1. Результат возвращается в виде значения Variant, содержащего массив. Результирующий массив строится по следующему правилу. Функция создает копию массива arrayName и в процессе поэлементного копирования проверяет, имеется ли очередной элемент массива arrayName в массиве v2. Если совпадение обнаружено, в результирующий массив помещается элемент массива v3, находящийся на той же позиции в v3, что и совпавший в v2. Если индекс совпавашго элемента в массиве v2 больше размерности массива v3, то копируется пустой элемент - 0 или пустая строка. Очевидно, что размерность массива-результата равна размерности исходного массива arrayName. При выборе элемента из массива v3 используется не абсолютное значение индекса элемента в v2, а относительное. Лучше показать это на примере. Предположим, массив v2 имеет индекс (-10, 0), а массив v3 - (1, 10). Тогда элементу v2(-10) соответствует элемент v3(l), элементу v2(-l) — v3(10), а индекс элемента v2(0) уже выходит за пределы размерности v3. В первой реализации функции (на момент написания этих строк имеется только версия 5.0) не производится никакого преобразования типов данных элементов массивов. Это означает, что совпадение элементов массивов arrayName и v2 может быть обнаружено только тогда, когда элементы имеют одинаковый тип. Это видно и из примеров 2 и 3, Кроме того, первый опыт использования этой функции показывает, что не производится сравнение элементов типа дата/время. Это видно в примере 1. Пример 1. Option Declare Dim vl(2) As Integer, v2(2) As Integer, v3(0) As Variant, __ v4 ( 0) as Variant Dim resl, res2, res3 Dim i as Integer vl(0) = 1 vl(1) = 2 vl(2) = 9 ' массив vl = [1, 2, 9] v2(0) = 1 v2(l) = 2 © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 271 v2(2) = 3 ' массив v2 = [1, 2, 3] v3(0) = Today ' массив v3 - [ 2 0 . 0 5 . 9 9 ] v 4 ( 0 ) = Cstr (v3 ( 0 ) ) ' массив v4 = [ " 2 0 . 0 5 . 9 9 " ] resl = Arrayreplace (vl, v2, v3) ' resl = [ 2 0 . 0 5 . 9 9 , 0, 9] For i% = Lbound(resl) To Ubound (resl ) Print r e s l ( i % ) , Typename (resl ( i% ) ) Next ' выводит : 1 20.05.99 DATE ' 0 INTEGER ' 9 INTEGER res2 = Arrayreplace (v3, v3, 999) 1 res2 = [ 2 0 . 0 5 . 9 9 ] 1 не работает сравнение элементов типа DATE гезЗ = Arrayreplace (v4 , v4 , 999) ' res3 = [999] но работает сравнение Variant, ' содержащего строку 1 Пример 2. Не сравниваются элементы массивов разных типов Dim v l ( l ) As Integer, = "some value" resl = Arrayreplace (vl , resl = [1, 9] v2(l) As String, v3(0) As Variant v2, v3) % Пример З. Даже для массивов одинаковых типов Variant сравниваются элементы только одинаковых типов. Если бы преобразование типа имело место, то 2 и "2" считались бы одинаковыми и массив-результат имел бы вид ["some value", 0] Dim v l ( l ) As Variant, v 2 ( l ) As Variant, v3(0) As Variant Dim resl vl ( 0 ) = 1 vl( 1 ) - 2 v2(0) - 1 ' - • v2(l) = "2" v3( 0 ) = "some value" resl = Arrayreplace(vl, v2, v3) " resl = ["some value", 2] . . . © Функция FullTrim FullTrim ( expr ) expr - выражение типа Variant, содержащее массив или строку. Для аргумента-массива функция удаляет «пустые» элементы. То, какой элемент считается пустым, зависит от типа массива. Для аргумента-массива функция удаляет «пустые» элементы. То, какой элемент считается «пустым», зависит от типа массива. Так, в массиве строк «пустыми» считаются элементы "" (пустая строка). В числовом массиве «пустые» элем енты — это нулевые © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 272 элементы. В массиве типа Variant «пустыми» также считаются элементы со значениями Empty и Null. Очевидно, что после удаления «пустых» элементов размерность результирующего массива может уменьшиться. Если все элементы массива оказались «пустыми», возвращается массив с единственным «пустым» элементом. На момент написания этих строк была доступна только версия Notes 5.O. И в ней, вопреки утверждениям документации, значения элементов массива Empty и Null не считались пустыми и оставлялись функцией FullTrim без изменений. Этот факт иллюстрируется примером. Об использовании этой функции для удаления пустого пространства из строки на стр. 253. Пример. Удаление "пустых" элементов массива. Dim StrArr(2) As String Dim NumArr(2) As Integer Dim VarArr(6) As Variant StrArr(O) = "aaa" : StrArr(l) = "" : StrArr(2) = "bbb" ' Массив StrArr: ["aaa", "", "bbb"] NumArr(O) = 1 : NumArr (1) = 0 : NumArr (2) -- 2 Массив StrArr: [1, 0, 2] 1 ' VarArr(O)- специально не заполняем - он останется Empty VarArr(l) = "QWERTY" VarArr(2) = "" VarArr(3) = 0 VarArr(4) = 1 2 VarArr(5) = Now VarArr(6) = Null ' Массив VarArr: [,"QWERTY", "", 0, 12, 23.05.99 20:21:34, Null] Dim vl, v2, v3 vl = Fulltrim(StrArr} v2 = Fulltrim(NumArr; v3 = Fulltrim(VarArr) 1 Массив v3: [,"QWERTY", 12, 28.05.99 20:21:34, Null] ' Значения Empty и Null остались! 2.8.7. Операции с окнами Функция InputBox InputBox[$] ( prompt f, [ title ] [, [ default ] [, xpos , ypos ] ] ] ) Выводит на экран диалоговое окно с сообщением, определенным пользователем, и возвращает введенную пользователем строку. prompt - строковое выражение, значение которого выводится в диалоговое окно, длина выражения prompt не должна превышать 128 символов. title - опция, являющаяся строковым выражением. Значение title выводится в заголовок диалогового окна. Максимальная длина значения title не должна превышать 128 символов. Если значением опции title является пустая строка - заголовок окна будет пустым. Если для пустого значения title установлены координаты xpos и ypos, в заголовок окна выводится запятая. © InterTrust Со. Тел. (095)9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 273 default - опция, являющаяся строковым выражением. Значение опции default выводится в диалоговое окно, как установленный по умолчанию, ответ пользователя. Длина строки default не должна превышать 512 символов. Если значением опции default является пустая строка и определены координаты xpos и ypos, в поле ввода ответа пользователя выводится запятая. xpos - опция, являющаяся числовым выражением, определяющим смещение левой границы диалогового окна от левой границы экрана в специальных единицах 1/1440 inch (.05 point). Если определено значение xpos, необходимо определить и значение ypos. ypos - опция. , являющаяся числовым выражением, определяющая смещение верхней границы диалогового окна от верхней границы экрана в специальных единицах 1/1440 inch (.05 point). Если определено значение ypos, необходимо определить и значение xpos. Функция InputBox возвращает значение типа Variant, содержащее строку. Функция InputBoxS возвращает строку типа String. Функция InputBox выводит на экран диалоговое окно, содержащее кнопки OK, Cancel, поле для ввода текста пользователем, при этом выполнение скрипта приостанавливается до момента, пока пользователь не нажмет кнопку ОК или Cancel. Если нажата кнопка Cancel, то возвращается пустая строка ("")• Пример. Введенный пользователем текст преобразуется в целое число. Dim num As Integer . . . num% '= Cint(Inputbox$("How many do you want?",_ "Numeric value input","2")) Функция и оператор MessageBox Функция: MessageBox ( message [, f buttons + icon + default •+ mode ] [, boxTitle ] ] ) Оператор: MessageBox message [, [ buttons + icon + default + mode ] [, boxTitle ] ] Выводит на экран сообщение в окне сообщения и ждет ответа пользователя. Функция возвращает значение, приписанное кнопке, нажатой пользователем. Функция и оператор MessageBox идентичны, только функция возвращает значение, а оператор - нет. message - сообщение, выводимое в окно сообщений, длиной до 512 символов. buttons - определенные числами или значениями констант из следующей таблицы кнопки, представленные в окне сообщений. Имя константы Значение Кнопка МВ_ОК 0 OK MB_OKCANCEL 1 OK и Cancel MB_ABORTRETRY1GNORE 2 Abort, Retry, и Ignore MB_YESNOCANCEL 3 Yes, No, и Cancel © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 274 MB_YESNO 4 Yes и No MB_RETRYCANCEL 5 Retry и Cancel icon - определяет пиктограммы, выводимые в окно сообщения. Значение icon определяется из следующей таблицы. Имя константы Значение Пиктограмма MBJCONSTOP 16 Знак Stop MBJCONQUESTION 32 Знак вопроса MB ICONEXCLAMATION 48 Восклицательный знак MBJCONINFORMATION 64 Информация default - определяет по умолчанию специальные кнопки, выводимые в окно сообщения. Нажатие клавиши ENTER для такой кнопки эквивалентно клику по клавише "мыши". Значения кнопок "мыши" в окне определяются следующей таблицей: Имя константы Значение Кнопка "мыши" MB_DEFBUTTON1 0 1 -я кнопка MB_DEFBUTTON2 256 2-я кнопка MB_DEFBUTTON3 512 3-я кнопка mode - определяет действие кнопок окна сообщений. Следующая таблица представляет список действий, производимых кнопками окна сообщений. Имя константы MB_APPLMODAL MB SYSTEMMODAL Значение 0 4096 Действие Останавливает выполнение текущего приложения до тех пор, пока пользователь не отреагирует в окне сообщения нажатием кнопки. Останавливает выполнение всех приложений до тех пор. пока пользователь не отреагирует в окне сообщения нажатием кнопки. boxTitle - строка, выводимая в заголовок окна сообщения, длиной до 128 символов. Функция MessageBox возвращает целое число от 1 до 7, включительно. Это значение определяет, какая кнопка была нажата пользователем в окне сообщения. Соответствие между значениями функции и значением кнопок приведено в следующей таблице. Возвращаемое Кнопка значение Константа 1 ОК IDOK 2 Cancel IDCANCEL 3 Abort LDABORT 4 Retry 1DRETRY 5 Ignore IDIGNORE © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 6 Yes IDYES 7 No IDNO 275 Все значения констант, представленные в этих таблицах, содержатся в ф айле LSCONST.LSS. Для использования значений констант, хранящихся в этом файле, его необходимо включить в скрипт с помощью директивы %Include. Пример 1. Вывод запроса: " Вас еще не утомили эти функции?" в окне с заголовком " Вопрос толстой книги ", содержащем кнопки Yes и No. Значение, возвращаемое функцией MessageBox присваивается переменной answer. % Include "LSCONST.LSS" Dim boxType As Long, answer" As Integer boxTypeS = MB YESNO + MB_ICONQUESTION ' answer% = MessageBox("Вас еще не утомили эти функции?", ЬохТуре&, _ "Вопрос толстой книги") Л После нажатия кнопки Print answer% (предположим, ' Выводит 6 Yes) ' выводим результат Пример 2. Оператор MessageBox выводит в окно сообщений с заголовком "Demo" и кнопкой ОК несколько строк. %Include "LSCONST.LSS" Dim twoLiner$ As String twoLiner$ = !Многострочное сообщение! MessageBox twoLiner$, MB_OK, "Demo" twoLiner$ = {Многострочное}+Chr$(10)+{ сообщение} MessageBox twoLiner$, MB OK, "Demo" Л Получаем подряд два одинаковых сообщения: . . . . •-,.---. Оператор ActivateApp (активизировать окно) ActivateApp windowName Активизирует окно приложения, имеющее указанный заголовок. windowName - текст заголовка активизируемого окна - строковое выражение, без учета регистра. При поиске окна учитывается лишь вхождение текста из строки windowName слева в заголовок. Например, если необходимо активизировать окно Notes с заголовком "Lotus Notes Workspace", то в качестве windowName достаточно задать "Lotus Notes". Если в списке имеющихся окон окажется несколько с одинаковым или подобным заголовком, будет активизировано первое найденное окно. | InterTrust Co. Тел. (095) 9567928 Язык LotusScript 276 Учтите, что ActivateApp только активирует окно (т.е. передает ему фокус ввода), но не может восстановить в нормальный размер или максимизировать, если окно свернуто. Для восстановления размеров окна или максимизации следовало бы послать этому окну "серию нажатий клавиш, используя оператор SendKeys. Пример. Активирует окно с заголовком "Lotus Notes - Workspace". ActivateApp "Lotus Notes" ,-,, Оператор SendKeys SendKeys string [, processNow ] Строка string содержит последовательность клавиш клавиатуры, имитацию нажатий которых в активном окне выполняет этот оператор. Имеется целый ряд соглашений, как в строке кодируются клавишные комбинации: {F4}, {CAPSLOCK}, {RIGHT 3}... К сожалению, в реализации LotusScript для Notes этот оператор не поддерживается. В качестве компенсации читателю предлагается пример, в котором необходимый эффект достигается путем вызова соответствующих функций Windows API. Пример можно найти в главе, посвященной обращению к внешним С-функциям на стр. 337. 2.8.8. Специальные функции и операторы Оператор Веер (звуковой сигнал) Веер Издает простой звуковой сигнал. Для воспроизведения более сложных звуков можно воспользоваться либо новым методом Play Tune класса NotesUlWorkspace (см. стр. 711), либо использовать средства Winodws API (см. пример на стр. 331) ФункцияCommand. ":; .-'••.".•.'. : •••' •••:••">-,•••:'/•'•:.:.:.;•-:--:.".•••..••:•"": •:•••••;•••••'-'•:--••". ........... • .; Command[S] Возвращает строку параметров, которая была передана при запуске приложению Lotus, использующему LotusScript, или пустую строку (""), если приложение было запущено без параметров. Функция Command возвращает значение типа Variant (String). Функция Commands возвращает строку. Пример. Определяется наличие параметров в командной строке. If Command$() = "" Then Print "Notes запущен без параметров" Else Print " Notes запущен с параметрами: " + Command$() End If ФункцияEnviron.';•/•.: ••:•."'•••: "•.. -..-:•'••• ~^-~•••• • •...". ••:. ... -;.'.'.•'•••.•••••'-^--у••/•'.:.:•;.:;.......•::...•.;.•--.:--........• Environ[$] ( { environName | n } ) Возвращает информацию, содержащуюся в переменной среды операционной системы. environName - строка символов верхнего регистра, определяющая имя переменной среды, n число от 1 до 255, включительно, определяющее положение переменной среды в таблице i InterTrust Co. Тел, (095) 9567928 Lotus Domino R. 5: (^-формулы, LotusScript, встроенные классы LotusScript и Java 217 переменных среды. Функция Environ возвращает значение типа Variant, а функция EnvironS возвращает значение типа String. Если для определения имени переменной среды используется environName, возвращается значение, определенное переменной среды. Если переменная среды не найдена, возвращается пустая строка (""). Если строка environName - пустая строка, или строка содержащая значение Null или Empty, то генерируется ошибка. Если позиция переменной среды определена числом п, возвращается строка с именем переменной среды и ее значением. Если значение п превышает действительное число строк в таблице, то возвращается пустая строка (""). Если п меньше 1 или больш е 255, то генерируется ошибка. Пример. Microsoft Windows 3.1 хранит временно существующие рабочие файлы в каталоге, объявленном в переменной среды с именем Temp. Введенная пользователем строка выводится в файл MYAPP.TMP в этом каталоге. Для определения пути к временному каталогу см. команду Set Temp в своем AUTOEXEC.BAT. Dim TempDir As String, tempFile As Integer . • .Dim tempFileName As String, tempStuff As String tempStuff$ = InputBox("Enter some temporary information") TempDir$ = Environ("Temp") , ChDir TempDir$ tempF.ile% = FreeFileO tempFileName$ = "myapp.tmp" Open terrtpFileName$ For Output As tempFile% Print #tempF.ile%, tempStuff $ " Close tempFile% . .. Функция Shell Shell (program [, windowStyle ] ) Запускает программу. Program - строковое выражение, значение которого определяет имя запускаемой на выполнение программы, program должно быть именем исполняемого файла с расширением ВАТ, COM, PIF, или ЕХЕ. Указание расширения или включение полного пути в спецификацию файла программы необязательно. Запуск с помощью функции Shell на выполнение внутренней команды DOS вызывает ошибку. WindowStyle - опция, являющаяся числом, определяющим стиль окна запускаемого приложения; она дается следующей таблицей. Стиль (Style) Описание Константа 1,5 или 9 Нормальное с фокусом SHELL_NORMAL_FOCUS 2 Минимизированное с фокусом (по умолчанию) SHELLJV11NJFOCUS 3 Максимизированное с фокусом SHELL JV1AX_FOCU S 4 или 8 Нормальное без фокуса SHELL_NORMAL_NO_FOCU S 6 или 7 Минимизированное без фокуса SHELL_MIN_NO_FOCUS Эти константы определены в файле LSCONST.LSS. Для обеспечения возможности использования этих констант включите этот файл в скрипт. © InterTrust Co. Тел. (095) 9567928 Язык LotusScript -" ' ' ; '-'- 278 " •> ,v Если используется операционная система Windows 3.1 и LotusScript успешно запускает программу, Shell возвращает идентификатор запущенной задачи. Если используется ОС Windows NT и LotusScript успешно запускает программу, Shell возвращает число 33. Если LotusScript не может запустить программу, Shell возвращает ошибку. • , '--.-••*-• Shell может вызываться из выражения или оператора присваивания, если они возвращают используемое этим оператором значение. После выполнения Shell, LotusScript продолжает выполнение скрипта, не ожидая завершения выгюлнеуия запущенной программы. Пример. Запуск приложения Windows Calculator в нормальном режиме. Dim taskld As Integer taskld% = Shell("CALC.EXE", 1} , > . Функция и оператор Yield , ' '•' , *- ':-: • ' ^ Yield Функция и оператор Yield передают управление операционной системе, а выполнение текущего процесса "встает в очередь". ОС Windows не может вернуть управление процессу до тех пор, пока не обработает все стоящие в очереди запросы. Оператор и функция Yield допустимы внутри процедуры или класса и не допустимы в модуле. Функция Yield возвращает значение типа Integer равное 0. ., Пример. Объявление для Windows 3.1 API функции, передача управления программе CALC.EXE, ожидание завершения ее выполнения, выдача сообщения о завершении выполнения программы CALC.EXE и продолжение выполнения скрипта. Авторы не рекомендуют относиться к этому примеру как к "боевому приему" для разработки приложений Notes. Во-первых, в 16-разрядной версии Windows пример хотя и работает, но не вполне корректно. Во-вторых, в 32-разрядных версиях Windows функция Shell возвращает 33, а не идентификатор задачи, а функция GetModuleUsage более не применяется. Declare Fun ctio n GetMod uleUsage Lib "Kernel"^ . . . "' ; (ByVal taskID As Integer) As Integer . * ' ' ' : • ". i " ', :'.' -': ' "" Sub DoCalc ' '...-. ,:• !; n:;" i"« . - • . - ! . • - - • : . ••:•.•'••..-. v. /'";. ' ' •-.••••••• Dim taskID As Integer -.-• . ' • • ' • • - •'• • - ' • ' ' ' •-"•'••''' taskID% = Shell ("CALC.EXE", ! ) • • ' ' ' ' ":";"' \-v'^ :^-> •'•• ":. Do While GetModuleUsage (taskID%) > 0 _• . ., ...... ; Yield "' " _ . - ' - . ; / ..-:: : Loop ' ' . . . . . . . . . MessageBox "Calculations done" End Sub . , DoCalc . 'Вызов подпрограммы DoCalc " • ' '' '" ' : ' : ; Оператор Stop Stop , . . . . . . , В режиме отладки скрипта имитирует наличие точки останова (breakpoint). При выполнения скрипта вне отладчика никак себя не проявляет. Очень простой и в то же время полезный оператор. Используя данный оператор можно съэкономить ощутимое время на отладке скрипта (особенно таких, как скрипт события QuerySave формы). , ' • • _ • . ' ] • ' " ' • ; • ' . • ' • . * • -••• •••••' .•'•:'" © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @гформулы, LotusScript, встроенные классы LotusScript и Java 279 2.8.9. Функции проверки значений Функция IsEmpty IsEmpty (expr ) Проверяет, является ли значение выражения ехрг значением Empty. Возвращает True, если значением выражения ехрг является значение Empty. Это бывает только в случае, когда значение выражения ехрг имеет тип Variant и является пустой строкой. В противном случае функция IsEmpty возвращает значение False (0). Пример. Dim dynaVar As Variant Print IsEmpty(dynaVar) dynaVar = PI Print IsEmpty(dynaVar) 'Выводит: True 'Выводит: False Функция IsNull IsNull (expr ) Возвращает True, если значением выражения ехрг является значение Null. В противном случае возвращает False. Пример. Dim v As Variant Print IsNull(v) Print IsEmpty(v) v = Null Print IsNull(v) Функция IsNumeric . 'Выводит: 'Выводит: False True 'Выводит: True . . . . •...... • .•-••..•;. :. •.....:...•-•...•:... .•:••-:••:... IsNumeric ( expr ) Возвращает True, если значение выражения ехрг является числом или может быть преобразовано в число. Значения следующих типов являются числом: Integer, Long, Single, Double. Currency, Date/Time, Empty, String (если преобразуется в число), OLE-ошибка, Boolean (True, False). Если значение выражения ехрг не является числом и не может быть преобразовано в число, функция возвращает False. Следующие значения или типы не могут быть числовыми: Null, Array, List. Пример. Dim v As Variant Print IsNumeric(v) 'Выводит: v = 12 Print IsNumeric(v) 'Выводит: 'Строка, не преобразуемая в число v = "Twelve" Print IsNumeric (v) 'Выводит: 'Строка, преобразуемая в число v = "12" Print IsNumeric(v) 'Выводит: True (v имеет значение Empty) True E'alse •- • True ФуНКЦИЯ' IsDate' '"• ; v:-: Г. :..• -- -:•':--. -•; •::;:," • :.-: -.' •. ••;.. . . . . • ..... ::-••...••...•-:..'.••.• '•••.. .....-...:••.....•..,. . ' . . . ...'..-. . IsDate (expr ) © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 280 ' • Проверяет, является ли значение выражения expr значением даты-времени. Возвращает значение True, если значением выражения expr является: • выражение типа Variant DataType? (Date/Time); • выражение типа Variant (String), представляющее значение даты-времени; • выражение типа String, представляющее значение даты-времени. В противном случае возвращает значение False. Пример. Функция IsDate проверяет значения переменных х, у, z на соответствие значению даты/времени. Dim x As Variant, у As Variant, x =~ 100 у = CDat(lOO) z - "Nov 2, 1983" P r in t I s D a te ( x ) Print IsDate( у ) Print IsDate( z ) Print: IsDate ("100") P r in t I s Da te(" N ov 2, 1983") z As Variant 'Числовое значение 'Числовое значение 'Строка, представляющая дату 'Выводит: False 'Выводит: True 'Выводит: True 'Выводит: False 'Выводит: True Функция IsScalar IsScalar ( expr) Проверяет, является ли тип значения выражения expr скалярным типом. Возвращает True, если значение выражения expr равно или имеет тип: Empty, Integer, Long, Single, Double, Currency, Date/Time, String, OLE-ошибка, Boolean (True, False). Иначе (если значением выражения expr являются: массив, список, объект, значения Nothing или Null), функция возвращает значение False. Пример. Dim var As VariantPrint IsScalar(var) var = 1 Print. IsScalar (var) • var == "hello" Print IsScalar(var) Class SenClass ' . . . объявление класса End Class Set var = New SenClass Print IsScalar(var) Dim senArray(l To 5) var - senArray Print IsScalar(var) Dim senList List var = senList Print IsScalar(var) 'Выводит: True 'Выводит: True 'Выводит: True ; 'Выводит: False 'Выводит: False 'Выводит: False .( Функция IsArray IsArray ( expr) Проверяет, является ли значение выражения expr массивом. Возвращает значение True, если значение выражения expr является массивом, в противном случае False. Пример. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Dim arrayFixed(1 To 5) Dirr. arrayDynam ( ) Print IsArray(arrayFixed) Print IsArray(arrayDynam) ' Выводит: ' Выводит: Dim v As Variant. Print IsArray(v) v = arrayFixed Print IsArray(v) 281 True True ' Выводит: False ' Выводит: True Функция IsList IsList ( expr) Проверяет, является ли значение выражения expr списком. Возвращает True, если значение выражения expr является списком. В противном случае возвращает False. Пример. Dim nryList List. Print IsList(myList) Dim v As Variant Print IsList(v) v - myList Print IsList(v) ' Выводит: True ' Выводит: False ' Выводит: True Функция ListTag ListTag ( refVar) Возвращает имя текущего элемента из списка, поэлементно обрабатываемого оператором ForAll. Параметр refVar - ссылка на переменную, определяющую в операторе ForAll. Функция применяется только внутри блока ForAll. Выдает ошибку, если значение refVar не является ссылкой на переменную, определенную в операторе ForAll. Пример. Печать имен элементов списка Loft. Dim loft. List As Integer loft%("first") = 0 loft.% ("second") = 1 lo ft%("third") =2 ForAll i In Loft% Print ListTag( i ) End ForAll ' Выводит : '- i ' first ' second 'third ; ' •-.... Функция IsElement IsElement ( listlN'ame ( stringExpr ) ) Проверяет, является ли строковое выражение stringExpr элементом списка HstName. Возвращает значение True, если в списке HstName содержится элемент с именем stringExpr, иначе возвращает False. Если предложение HstName не является именем объявленного списка, LotusScript выдает ошибку. Если значением выражения expr является числовое выражение, LotusScript преобразует его значение в строковое выражение. © InterTrust Со. Тел. (095) 9567928 282 ; Язык LotusScript Пример. Создается список элементов, которым присваиваются некоторые значения. Выдается запрос на идентификацию удаляемых из списка элементов. Если в empNameS есть элементы для удаления из списка, то происходит удаление указанных элементов из списка. В противном случае выдается соответствующее сообщение и выполнение скрипта прекращается Dim empList List As Double Dim empName As String, Id As Double, found As Integer empList#("Maria Jones") = 12345 empList#("Roman Minsky") = 23456 empListtt("Joe Smith") = 34567 empListJ ("Sal Piccio") = 91234 empName$ = InputBox$("Which employee is leaving?") If IsElement(empList#(empName$)) = True Then Id# = CDbl(InputBox$("What's " & empName$ & "'s Id?")) found% = False ' Initialize found to 0 (False) ForAll empld In empList# If empld = Id# Then found% = True ' Set found to -1 (True). If ListTag(empld) = empName$ Then Erase empListt(empName$) 'Проверка элемента, удаляемого из списка. If IsElement(empList#(empName$)) = False Then MessageBox empName$ & " has been removed from the list." End If Else MessageBox "Employee name and Id do not match." End. If Exit ForAll End If •' ' End ForAll ' ' If found* = False Then MessageBox "Not a valid employee Id." End If Else MessageBox "We have no such employee." End If Функция IsUnknown IsUnknown ( expr) Проверяет, является ли значение выражения expr значением OLE V_I UNKNOWN. Возвращает значение True, если значение выражения expr имеет тип Variant и равно V_I UN KNOWN. Такое значение может иметь только ссылка на OLE-объект. В противном случае функция возвращает False. Функция IsDefined IsDefmed ( stringExpr) Проверяет, является ли значение строкового выражения stringExpr именем константы, определенной в Lotus-продукте. Возвращает значение True, если значение выражения stringExpr определено в Lotus-продукте, иначе возвращает False. Обычно функция используется для проверки значения констант, идентифицирующих используемую платформу. Такие проверки могут использоваться в %lf директиве условной компиляции скрипта. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 283 2.8.10. Средства работы с файловой системой 2.8.10.1. Операторы и функции для работы с устройствами и каталогами Оператор ChDir (назначить каталог) ChDir path path - строковое выражение, представляющее каталог, назначаемый в качестве текущего. Назначает в качестве текущего (рабочего) каталога каталог, путь к которому указан в выражении path. Если первым символом выражения path не является символ, обозначающий дисковое устройство (диск), то в качестве рабочего используется текущий диск, в противном случае рабочим становится диск, обозначение которого присутствует в выражении path. Формат и максимальная длина выражения path должны соответствовать соглашениям, принятым в используемой платформе. Пример 1. Назначает устройство (диск) D текущим устройством, ChDrive "D" . Пример 2. Назначает каталог TEST текущим каталогом на устройстве С. ChDir "C:\TEST" Пример 3. Назначить каталог TEST текущим каталогом на текущем устройстве D. ChDir "\TEST" Print CurDir () 'Выводит D:\TEST Оператор ChDrive (назначить устройство) ChDrive drive drive - строка, представляющая существующее устройство. Оператор ChDrive назначает текущее устройство согласно значению строки drive. Текущее устройство - это устройство, которое используется, если происходит обращение к указанному пользователем файлу, или при использовании пути, в котором отсутствует спецификация устройства. Если значением строки drive является пустая строка (""), то оператор ChDrive не меняет назначение, оставляя текущим устройство, используемое до выполнения оператора ChDrive. Если значением строки drive является строка, содержащая более одного символа, в качестве обозначения переназначаемого устройства берется первый символ значения строки drive. Оператор ChDrive не требует наличия знака двоеточие ( : ) после символа, обозначающего назначаемое устройство. Символом, обозначающим устройство, может быть любая буква от А до буквы, представленной опцией lastdrive в системном файле CONFIG.SYS, включительно. Пример. Назначить D текущим устройством. ChDrive "D" ' ФуНКЦИЯCurDir . . • . - . . . . . ...•:.•,•"••.••.•. ..... -•-•.... • ' .-.:.....', .-••'-...--.. .. ;•...... -...-.. . .,...., CurDir[$] [ ( drive ) ] © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 284 Определяет назначение текущего каталога заданного устройства. CurDir возвращает значение типа Variant (String). CurDir$ возвращает значение типа String. drive - опция, являющаяся строковым выражением, определяющая существующее устройство. Если опция отсутствует, функция CurDir использует текущее устройство. Если спецификация устройства представляет собой строку, состоящую более, чем из одного символа, CurDir использует только первый символ строки. CurDir не требует наличия знака ( : ) после буквы, определяющей устройство. Пример. ChDir "C:\TEST" Print CurDir?() 'Выводит "C:\TEST" Функция CurDrive CurDrive[$] Возвращает строку, идентифицирующую текущее устройство (диск), состоящую из символа устройства, с последующим двоеточием. Функция CurDrive возвращает значение типа Variant (String). Функция CurDriveS возвращает значение типа String. Пример. Dim tempDrive As String tempDrive? = CurDrive?() If tempDrive? <> "C:" Then ChDrive "C" End If ChDir "\TEST" Print CurDir?() 'Выводит "C:\TEST" Функция Dir . . .• •. . . . • •. . . .,.:.... -• .... Dir[$] [ ( fileSpec [, attributeMask ] ) ] -. . ' - . . . , : Возвращает имя файла, каталога, или букву - название устройства. fiieSpec - строковое выражение, определяющее путь к файлу. Этот аргумент является обязательным только при первом обращении к функции Dir$ с указанием данного пути. Составленное по правилам определения пути к файлам, fileSpec обеспечивает доступ к файлам, синтаксис указателя пути к которым удовлетворяет принятой спецификации (например, использование в указателе пути знаков "*" и "?"). attributeMask - любое целое выражение, значение которого является возвращаемым именем. Если пропущен этот аргумент, имена существующих на устройстве файлов сравниваются со значениями, содержащимися в fileSpec. Если есть аргумент attributeMask, то должен быть и аргумент fileSpec. Для включения в возвращаемый список типов файлов, используются суммарные значения графы Mask из следующей таблицы, представляющей типы файлов: Mask Атрибуты файла Константа 0 Normal file ATTR NORMAL 2 Hidden file ATTRJHDDEN 4 System file ATTR SYSTEM © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 8 Volume label ATTR_VOLUME не Атрибуты файла hidden, system, или directory-имеют смысла для Volume label 16 285 Directory ATTR DIRECTORY Функция Dir возвращает значение типа Variant (String), а функция Dir$ - типа String. Константы, использованные в таблице, хранятся в файле LSCONST.LSS. Включение этого файла в скрипт позволяет использовать названия атрибутов вместо их численного кода. Для определения существования файла используется его правильное (в рамках используемой платформы) имя в качестве аргумента для функции Dir (Dir$). Возвращаемое значение может быть либо именем файла, либо сообщением об отсутствии файла на указанном устройстве. Первое обращение к функции Dir (Dir$) возвращает имя первого файла в указанном каталоге согласно спецификации имени файла в fileSpec. Последующие вызовы функции Dir (Dir$) с другими аргументами позволяют добавить имена файлов по списку fileSpec. Если в указанном каталоге больше нет файлов, соответствующих спецификации, то функция Dir возвращает значение типа Variant (String), а функция Dir$ возвращает пустую строку (""). Если, после получения пустой строки, функция Dir (Dir$) вызывается еще раз с той же спецификацией пути, то генерируется ошибка. Пример. Получения списка каталогов на устройстве С:\ Dim pathName As String, fileName As String pathName$ = "C:\*.*" fileName$ = Dir$(pathName$, 0) Do While fileName$ <> "" • Print fileNameS fileName$ - Dir$() Loop . • . Оператор MkDir (создать каталог) MkDirpath path - строковое выражение, значение которого является именем создаваемого каталога. В выражении path буква, определяющая дисковое устройство, не является обязательной. Если она отсутствует, то используется текущее назначение устройства. Правила указания каталога должны соответствовать правилам используемой операционной платформы. При невозможности создать требуемый каталог LotusScript выдает ошибку. Пример. Создание каталога TEST в корневом каталоге устройства С. MkDir "C:\TEST" -<• ' " Оператор Name (переименовать/переслать файл/каталог) Name oidName As newName Переименовывает (и/или пересылает) файл или каталог. oldName - строковое выражение, определяющее имя существующего файла/каталога, необязательно содержащее путь; newName - строковое выражение, определяющее новое имя файла/каталога, необязательно содержащее путь. Для пересылки файла необходимо указывать полный путь и для файла с именем oidName и для файла с именем newName. Для переименования используйте имя файла в обоих аргументах. © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 286 Для пересылки файла с одного устройство на другое необходима ОС Windows NT или Windows 95. Пример. Переименование файла с именем TEST], находящегося в каталоге WINDOWS на устройстве С, в файл с именем TEST2 и пересылка переименованного файла в корневой каталог устройства С. Name? "C:\WINDOWS\TEST1" As "C:\TEST2" . , , - ;lf ,, ,. Оператор RmDir (удалить каталог) RmDir path path - строковое выражение - указатель пути к удаляемому каталогу. Максимальная длина указателя пути к каталогу определяется рамками используемой платформы. Если имя каталога в указателе пути отсутствует, то вырабатывается ошибка. Пример. Удаление каталог а C:\TEST из файловой системы RmDir "C:\TEST" 2.8.10.2. Операторы и функции для работы с файлами Функция FileAttr FileAttr ( fileNumber, attribute ) Возвращает значение типа доступа или значения системных атрибутов для открытого файла. fileNumber - номер, присвоенный файлу при его открытии. attribute - число (1 или 2), специфицирующее тип используемой информации Вместо 1 или 2 можно использовать для спецификации соответствующие этим значениям константы ATTR MODE или ATTR_HANDLE. Эти константы определены в файле LSCONST.LSS. Включение этого файл в скрипт с помощью директивы %Include позволит использовать значения текстовых констант вместо числовых значений. Если значением атрибута является строка ATTR_HANDLE, то функция FileAttr возвращает системные атрибуты файла. Если значением атрибута является строка ATTR_MODE, то функция FileAttr возвращает целое число, определяющее тип доступа к файлу, согласно следующей таблице: Возвращаемое значение Тип доступа Константа 1 Input ATTR JN PUT 2 Output ATTR_OUTPUT 4 Random ATTR_RANDOM 8 Append ATTR_APPEND 32 Binary ATTRJBINARY © InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 287 Пример. Открывается (создается) файл с именем DATA.TXT и на экран выводится значение типа доступа к этому файлу. '«Include "LSCONST.LSS" Dim mode As String, msg As String Dim hdl As Integer, fileNum As Integer fileNum! = FreeFile() Open "DATA.TXT" For Append As fileNum% Select Case FileAttr(fileNum*, ATTR_MODE) Case 1 : mode$ = "Input" - .,.-Case 2 : mode$ = "Output" Case 4 : mode$ = "Random" Case 8 : mode$ = "Append" Case 32: mode$ = "Binary" End Select . Close fileNum% Print "DOS File Mode = "; mode$ . - Функция FileDateTime FileDateTime (fileName ) Возвращает дату и время создания или последней модификации файла. fileName - строковое выражение, которое может содержать путь к файлу в рамках синтаксиса используемой платформы. Функция возвращает дату и время создания или последней модификации файла в формате, соответствующем используемой операционной платформе или в международном формате. Если файла с указанным именем нет по указанному пути, возвращается сообщение об ошибке. Пример. Создается файл с именем DATA.TXT и выводится дата и время его создания. % Include "LSCONST.LSS" Dim fileName As String, fileNum As Integer fileNum! = FreeFile() fileName$ = "DATA.TXT" Open fileName$ For Output As fileNum% ' Создание файла DATA.TXT Close fileNum! Print fileName$; " Nigaai "; FileDateTime(fileName$) ФункцияFileLen v;:. ....... ....:..:••:••-.. ... .................. :-.. :. FileLen ( fileName ) ...... ....... . ..... > Возвращает длину файла в байтах (тип Long). fileName - строковое выражение; может содержать путь и не может содержать специальные символы. Пример. Переменной verLen присваивается значение длины файла C:\CONFIG.SYS (в байтах) и выводится ее значение. Dim verLen As Long verLen& = FileLen("С:\CONFIG.SYS") Print verLen& - Функция GetFile Attr. ..,.,. •; ............ -..;-......::...... ............ •......:.••• ......... :•/•• ...•-.:.--••:,. ...•.,•...:.•.-• ... .-,.., . GetFileAttr (fileName ) © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 288 Возвращает значения системных атрибутов файла или каталога. <: : fileName - имя файла или каталога; при необходимости может содержать указатель пути к файлу или каталогу. Возвращаемым значением является число, равное сумме целых значений кодов значений атрибутов файла, согласно следующей таблице. Код значения Атрибут Константа 0 Normal file ATTR NORMAL 1 Read-only file ATTRJREADONLY 2 Hidden file ATTRJHIDDEN 4 System file ATTR_SYSTEM 16 Directory ATTR_DIRECTORY 32 File(archived) ATTR_ARCH1VE Константы представляют собой значения, определенные в файле LSCONST.LSS. Для обеспечения возможности использования имен этих констант, необходимо включить этот файл в скрипт. Пример. В режиме Output открывается (создается) файл с именем DATA.TXT, Вызывается функция SetFileAttr для установки ему аттрибутов Read-Only, System, Hidden, после чего с помощью функции GetFileAttr проверяются атрибуты этого файла и выводится соответствующее сообщение. ?Include "LSCONST.LSS" Dim fileNum As Integer, attr As Integer Dim fileNarne As String, msg As String ЈileNum% = FreeFile() fileName$ = "DATA.TXT" Open fileName$ For Output As fileNum% Close fileNum! SetFileAttr fileNaineS, ATTR READONLY + ATTR_SYSTEM + ATTR_HIDDEN attr% = GetFileAttr(fileName$) If (attr% And ATTR^READONLY) Then msg$ - msg$ & " Read-Only " Else msg$ = msg$ & " Normal " .•--.. End If If (attr% And ATTR_HIDDEN) Then msg$ = msg$ & " Hidden " If (attr% And ATTR_SYSTEM) Then msg$ = msg$ & " System " If (attr% And ATTR_DIRECTORY) Then msg$ = msg$ & " Directory " Print msg$ SetFileAttr fileName$, ATTR_NORMAL Kill fileName$ Оператор FileCopy (копировать файл) < FileCopy source , destination source - строковое выражение, определяющее имя копируемого файла, может включать указатель пути к этому файлу, destination - строковое выражение, определяющее имя файла -копии, также может включать указатель пути к файлу - копии. Перед копированием файл открывается в режиме Read. Выражения, определяющие исходный и результирующий файлы могут содержать специальные символы. Если © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 289 результирующий файл уже существует, он будет замещен копируемым файлом. Во избежание этого необходимо использовать функцию Dir, чтобы определить имена уже существующих файлов. Для установки атрибута файла "только для чтение" используется оператор SetFileAttr. Пример. Копирует файл C:\WINDOWS\APP.BAT в корневой каталог 'устройства С: имя копии APPLOAD.BAT. FileCopy "C:\WINDOWS\APP.BAT", "C:\APPLOAD.BAT" Оператор Kill (удалить файл) Kill fileName fileName - строковое выражение, являющееся именем файла; оно может содержать букву, определяющую устройство, и путь к файлу. Использование оператора Kill требует особого внимания, хотя чаще всего ошибочно удаленный файл можно восстановить с помощью соответствующей команды используемой платформы. Перед удалением файл должен быть закрыт. Kill удаляет файлы, но не каталоги. Пример. Удаление файла C:\TEST из файловой системы. Kill "C:\TEST" Оператор SetFileAttr (назначить файлу атрибуты) SetFileAttr fileName , attributes fileName- строковое выражение; может включать путь к файлу, attributes - атрибуты файла, определенные суммой любых кодов атрибутов из следующей таблицы. Значение Описание Константа 0 Normal file ATTR NORMAL 1 Read-only ATTR_READONLY 2 Hidden ATTRJrllDDEN 4 System ATTR_SYSTEM 32 Changed since last back-up ATTR_ARCHIVE Значения всех этих констант определены в файле LSCONST.LSS. Для использования значений констант необходимо включить этот файл в скрипт с помощью директивы %lnclude. SetFileAttr не применяется к открытому файлу, если только он не открыт в режиме "только 4TeHHe"(read-only). Пример. Создает файл и использует оператор SetFileAttr для назначения этому файлу атрибутов Read-Only, System, и Hidden. Затем, для проверки значений атрибутов файла используется оператор GetFileAttr и выводятся значения атрибутов. ^Include "LSCONST.LSS" Dim fileNum As Integer, attr As Integer Dim fileName As String, msg As String fileNum% = FreeFile() fileName? - "DATA.TXT" . . . . . © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 290 Open fileName? For Output As fileNum% . .-.-Close fileNum% SetF.ileAt.tr fileName$, ATTR_READONLY + ATTR_SYSTEM + ATTR_H1DDEN attr% = GetFileAttr(fileName$) If (attrli And ATTR_READONLY) Then msg$ = msg$ & " Read-Only " . Else msg$ = msg$ & " Normal " . ' . ' • • ; End It If (attr% And ATTR_HIDDEN) Then msg$ = msg$ & " Hidden " If (attr% And ATTR_SYSTEM) Then msg$ = msg$ & " System " If (attr% And ATTR_VOLUME) Then msg$ = msg$ & " Volume " If (attr% And ATTR_DIRECTORY) Then msg$ = msg$ & " Directory " Print msgS SetFileAt.tr fileName$, ATTR_NORMAL 'Восстановление ATTR_NORMAL Kill fileNameS 2.8.11. Операции ввода/вывода 2.8.11.1. Основные положения Описание типов доступа к файлам, используемых в LotusScript, представлено в следующей таблице. Тип доступа Последовательный Прямой Произвольный Описание Простой, чаще других встречающийся тип. Обычно, их содержимое -это строки текста, ограниченные символом конца строки. Чтение этих файлов чаще всего производится соответствующими текстовыми редакторами Содержит структурированные данные, которые не читаются обычным образом из LotusScript. Являются максимально удобными для манипулирования информацией на уровне байта, который, в свою очередь является минимально доступным уровнем в дисковых операциях Для записи или чтения информации из файла необходимо открыть файл. Открываемый файл идентифицируется номером в интервале от 1 до 255. Этот номер обычно используется, как идентификатор файла при выполнении операций ввода/вывода. (Только некоторые операции с файлом используют его имя вместо номера). Соответствие между именем и номером файла, определенное при его открытии, сохраняется до момента закрытия этого файла, после чего этот же номер может быть использован для операций с другим файлом. Замечание: в описании файловой системы используются названия операторов ввода/вывода. Подробное описание этих операторов представлено в конце раздела. Файл последовательного доступа Файл последовательного доступа является текстовым файлом, информация в котором хранится в виде символьных строк произвольной длины. Концом строки файла является символ перехода на новую строку. Данные файла не являются блочными записями. Такой файл не удобен для хранения информации в виде чисел, т.к. числа в нем представлены в виде символьных строк, что влечет за собой необходимость преобразования типа данных файла при выполнении расчетов или записи числовой информации в файл. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 291 Открытие файла последовательного доступа Файл последовательного доступа открывается в одном из следующих режимов: • Input (ввод); • Output (вывод); • Append (добавление). Уже открытый файл нельзя открыть еще раз. Для открытия файла последовательного доступа используется оператор Open. Файл, открываемый для чтения, обязательно должен присутствовать на диске, в противном случае генерируется сообщение об ошибочной попытке открыть несуществующий файл. Файл, открываемый для записи или добавления данных может не существовать, но, оператором Open, он будет создан автоматически пустым. Вывод (запись) данных в файл последовательного доступа Для записи значения переменной в файл последовательного доступа, открытый в режиме вывода или добавления, используется оператор Print # и Write # Ввод (чтение) данных из файла последовательного доступа Для чтения данных из файла последовательного доступа, последний открывается в режиме Input. Возможно использование операторов Line Input #, Input # или функции Input для ввода из файла значений переменных. Line Input # вводит из файла одну текстовую строку до символа "Конец строки", не включая этот символ в введенную строку. Например: "" . Do Until EOF(idFile) Line Input tidFile, Print iLine Loop iLine ' ' . , Эти операторы осуществляют чтение из файла по одной строке до конца файла. Оператор Print осуществляет вывод этих строк на экран дисплея, добавляя при этом в конец каждой строки признак "конец строки". Оператор input # может быть использован для ввода форматированных записей и записей, сделанных оператором Write #. Например, допустим, что файл с номером idFiie содержит следующую строку: "Testing",123,456,#Null#. Следующие операторы, считывая данные из этого файла, осуществляют присваивание соответствующих значений переменным в следующем порядке: Testing в HLabel; 123 в infA; 56 в supA; Null в tailV. Dim liLabel As String, tailV As Variant Dim infA As Integer, supA As Integer Input tidFile, liLabel, infA, supA, tailV Если предполагается частое использование операторов Write # и Input # для операций с файлами последовательного доступа, то лучше всего поменять стратегию организации обмена и перейти к работе с файлами прямого доступа. Эти тип файлов являются лучшим с точки зрения организации частого обмена данными между программой и диском. Для чтения данных из файла последовательного доступа может также использоваться функция Input. В © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 292 ' --'• ' • качестве параметра она использует число, указывающее количество вводимых символов, и возвращает строку из заданного количества символов при обращении к ней. Следующий пример демонстрирует применение этой функции для вычисления количества символов, содержащихся в файле: Dim fulFile As String fulFilea= lnput$(LOF(idFile), idFile) ' LOF возвращает длину файла, выраженную количеством символов в нем. Файлы прямого доступа Файл прямого доступа содержит ряд записей фиксированной длины. Запись может содержать значения типа Integer или String. Если запись содержит тип данных, определенный пользователем, то она может быть разбита на части соответствующего типа. По умолчанию, файл прямого доступа открывается без указания режима, обязательного для открытия файлов последовательного и произвольного доступа. Открытие файла прямого доступа Для открытия файла прямого доступа используется оператор Open. Если к моменту исполнения оператора Open файл не существовал, то он будет создан этим оператором пустым. Определение типа записи Т.к. все записи файла прямого доступа имеют одну и ту же, определенную длину, то тип данных такого файла определен с фиксированной длиной В противном случае, данные, прочитанные из файла прямого доступа, будут некорректны. Если длина выводимой в файл записи меньше установленной длины, то запись дополняется пробелами слева, если же длина больше установленной для данного файла запись "усекается" до нужной длины. Для простоты, все внутренние поля записи, определенной пользователем, имеют фиксированную длину. Если заранее известно, что для вывода в файл будут использованы записи разной длины, параметр Len должен иметь значение максимальной длины выводимых в файл строк, для чего необходимо предварительно оценить длину выводимых строк. Можно выбрать для операции ввода/вывода любую строку файла, указывая номер записи в операторах Get или Put. Пользователь может определить свой тип записи, который может иметь достаточно сложную структуру. Например, Type emploRec id As Integer salary As Currency hireDate As Double lastName As String * 15 firstName As String * 15 End Type ' ' ' ' ' тип Integers, длина 2 байта тип Currency, длина 8 байта тип Double, длина 8 байт Строка фиксированной длины - 30 ааёо Строка фиксированной длины - 30 ааёо Эта запись, длиной 78 байт, поддерживается в операторе Open с помощью указателя длины записи Len=78. Длина записи подобного типа может быть определена и в момент выполнения операции ввода - вывода с^томощью использования функции Len. Например: Dim recLen As Integer, idFile As Integer Dim recHold As emploRec idFile = 1 ' Номер открытого файла recLen = Len(recHold) ' Длина записи в этом файле Open "DATA.TXT" For Random As idFile Len = recLen © InterTrust Co. Ten. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 293 Ввод (чтение) данных из файлов прямого доступа Для чтения данных их файла прямого доступа используется оператор Get. Следующий пример демонстрирует чтение записи N 5 из файла с номером idFile в переменную recHold (предполагается существование записи N 5 в файле): Dim posit As Integer posit = 5 .. . - Dim recHold As emploRec Get idFile, posit, recHold Вывод (запись) данных в файл прямого доступа Для записи данных в файл прямого доступа используется оператор Put. Этот оператор либо добавляет новую запись к уже имеющимся в файле, либо перемещает существующую в файле запись на новое место (новый номер). Put используется со следующими параметрами: номер файла, к которому происходит обращение, номер записи, которая записывается в файл, имя переменной, содержащей выводимую в файл запись. Для перемещения записи в файле необходимо просто указать ее номер среди записей файла: Dim posit As Integer posit = 5 Перемещение записи 5 с использованием переменной recHold: Put idFile, posit, recHold Для добавления новой записи к файлу достаточно использовать номер записи, на единицу превышающий номер последней записи в файле. Так, чтобы добавить запись к файлу, содержащему 5 записей, используется номер записи 6. Для удаления записи из файла произвольного доступа надо перезаписать записи с номерами большими, чем номер удаляемой записи, уменьшив номер каждой из них на 1, т.о. из файла будет исключена запись, т.к. на ее место ( номер) будет записана следующая за ней запись. Например: Dim tempRec As emploRec For I = posit To lastRec - 1 Get idFile, I + 1, tempRec Put idFile, 1, tempRec Next I • Этот способ не исключает возникновения ошибок, связанных с появлением дублирующих записей в файле из - за ошибки определения начального номера сканирования. Более надежным, хотя и более сложным в реализации, является создание файла, в который копируются все записи, кроме удаляемой, затем исходный файл удаляется, а файл-копия переименовывается именем исходного файла. Двоичные файлы (произвольного доступа) Двоичные файлы представляют максимальные возможности управления операциями ввода - вывода данных. Недостатком этого способа доступа, называемого также произвольным доступом, является необходимость точно знать, как записывался этот файл, чтобы обеспечить правильный порядок чтения из него данных. Хотя очень немногие функции и операторы обеспечивают операции с двоичными файлами, в отличие от файлов последовательного и прямого доступа, тем не менее, двоичные файлы являются наиболее гибкими в смысле возможности управления ими. © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 294 Открытие двоичных файлов . ;? • Для открытия двоичного файла используется оператор Open. Если файл не существует, то при исполнении оператора Open он будет создан, пустым независимо от режима выполнения этого оператора (чтение или запись). Использование переменной длины нолей В отличие от файлов прямого доступа двоичные файла могут содержать записи переменной (не фиксированной) длины. Тем не менее, необходимо знать длину записей в порядке их следования в файле. Хорошим стилем программирования считается определение длины каждой записи в двоичном файле. Однако, это необязательно, если строка является составным, определенным пользователем типом. В этом случае, LotusScript автоматически присвоит длину соответствующего поля для каждой строки переменной длины. Двоичной доступ обеспечивает побайтный просмотр файла. Сам файл представляет собой последовательность байтов, которые могут быть как символьной, так и цифровой информацией. Вывод (запись) данных в двоичный файл Для записи в двоичный файл используется оператор Put. Ввод (чтение) данных из двоичного файла Для чтения данных из двоичного файла используется или оператор Get, или функция Input. Оператор Get, при отсутствии ошибок, считывает информацию из двоичного файла с указанного номера байта в переменную, которая может быть строкой переменной длины или переменной целого типа. Для строки переменной длины количество считываемых символов определяет длину этой строки. (Кстати, это количество может быть равным О, соответствующим образом определяя длину строки переменной длины). Поэтому, необходимо в первую очередь установить длину "принимающей" строки. Если строка в файле находится внутри типа, определенного пользователем, длина строки определяется с некоторым запасом. Например, можно удлинить строку для обеспечения разделения полей, содержащихся в строке. Функции Input и Input$ также используются для чтения данных из двоичного файла. 2.8.11.2. Операторы ввода/вывода Оператор Close (закрыть файл(ы)) Close [ [ # ] fileNumbe [ , [ # } fileNumbe ] ... ] Закрывает один или более открытых файлов, после записи содержимого всех внутренних буферов в эти файлы. fileNumbe - опция, являющаяся номером, присвоенным файлу в скрипте при его открытии. Если опция fileNumbe отсутствует, оператор Close без параметров закрывает все открытые файлы. Отсутствие знака (#) перед fileNumbe не влияет на выполнение оператора. Перед закрытием открытых файлов, оператор Close записывает содержимое всех внутренних буферов в эти файлы. Если LotusScript встречается с ошибкой периода выполнения для которой нет оператора On Error, LotusScript закрывает все открытые файлы. Если значение опции fileNumbe содержит дробную часть, LotusScript округляет его значение до целого значения. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-фортулы, LotusScript, «строенные классы LotusScript и Java 295 Пример. Open "c:\rab.asc" For Input Access Read Shared As 1 Len = 128 Close #1 Оператор Get (чтение из двоичного файла) Get [#] fileNumber , [ recordNumber ] , variableName fiieNumber - номер, присвоенный файлу при его открытии в операторе Open. Номеру предшествует символ #, имя файла и имя переменной, в которую производится считывание данных recordNumber - опция, определяющая позицию в файле (в двоичном файле - позицию байта, в файле произвольного доступа - позицию записи), из которой производится считывание. Если параметр recordNumber пропущен, считывание данных производится из текущей позиции файла. variableName - переменная, "принимающая" данные из файла. Первый байт или запись в файле имеют номер позиции 1. После выполнения каждого оператора чтения, значение номера увеличивается. Оператор Get считывает данные в переменную variableName определенного типа. Следующая таблица определяет "реакцию" оператора Get на различные типы данных переменной variableName. Тип variableName Действие Variant Оператор Get преобразует первые два байта к значению типа DataType и считывает их. Если значением DataType является значение Empty или Null, оператор Get останавливает ввод и присваивает переменной variableName значение Empty или Null. Если DataType - число, оператор Get считывает столько байтов, сколько помещается в типе Data Type: Integer - 2 байта; Long - 4 байта; Single - 4 байта; Double - 8 байт; Currency - 8 байт; Date/time - 8 байт. Строка фиксированной длины Оператор Get считывает определенное число символов, например, если переменная объявлена, как String* 10, оператор Get считает 10 символов. Строка переменной длины Оператор Get считывает данные в зависимости от типа файла. Произвольный: два байта, считанные первыми, определяют длину строки и Get считывает соответствующее число символов. Если значение variableName меньше числа записей в файле, данные считываются до тех пор, пока это позволяет значение variableName. После этого указатель устанавливается на следующую непрочитан-ную запись. Указанное число байтов считывается из файла в строку, длина которой определена в опции variableName. Если начальное значение опции не определено, данные из файла не считываются. Число байтов, считываемых из файла равно сумме байтов всех элеменотов определенного пользователем типа. Этот тип не может содержать элементов типа массив, список или объект. Двоичный Тип, определенный пользователем © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 296 Пример. Открывается файл произвольного доступа, длина записи в котором равна длине записи, указанной в переменной гее. Выводятся записи в указанные позиции файла. Выводятся значения записей. Type PersonRecord empNumber As Integer . .• . ;t, ., empName As String * 20 End Type Dim fileNum% As Integer Dim fileName$ As String Dim rec As PersonRecord fileNuml = FreeFile() fileName$ = "DATA.TXT" Open fileName? For Random As fileNum% Len = Len(rec) 'Вывод записи в 1 позицию, rec.empNumber% = 123 rec.empName$ = "John Smith" Put #fileNum%, 1, rec 'Вывод записи в 2 позицию, rec.empNumberl = 4 5 6 rec.empName$ = "Jane Doe" Put #fileNum%, 2, rec 'Вывод записи в 3 позицию, rec.empNumber% = 789 rec.empName$ = "Jack Jones" Put #fileNum%, , rec 'Возврат к началу файла и печать всех записей. Seek fileNum%, I Do While Not EOF(fileNum%) Get #fileNum%, , rec Print rec.empNumber%; rec.empName$ Loop Close fileNum% 'Печатаются следующие записи: ' 123 John Smith ' 456 Jane Doe ' 789 Jack Jones Оператор Input # ; . . - • . , . . : ' • ' ; " . ; " " . . • ' ' • • . . ...- • • • - . . . - • . • , • • • . . • ; , , •-.-:. .•..•. :?:; : :: '*.::;. Input #fileNumber, variableList Читает данные из файла последовательного доступа в переменную. tileNumber - число - номер открываемого файла. Номеру файла обязательно предшествует символ #. variableList - список переменных, разделенных запятой. Данные считываются из файла в назначенные переменные. Тип данных файла должен соответствовать типу данных этих переменных. Список variableList может включать в себя массивы, списки, переменные определенного пользователем типа, или переменные -ссылки. Можно использовать отдельные элементы массива, списка и, определенного пользователем типа или класса. Следующая таблица представляет для оператора Input # режимы чтения символов в зависимости от типа данных variableList. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 297 Тип данных в variableList Как Input # считывает символы Числовая переменная Первый символ в файле, отличный от пробела, становится первой цифрой числа. Встреченный пробел, запятая и символ конца строки в файле определяет конец числа. Пустые строки и нечисловые символы преобразуются в цифры 0. Строковая переменная Первый символ в файле, отличный от пробела, становится первой буквой строки. При формировании строки выполняются следующие условия: * если символ - ("), он игнорируется; но все символы следующие за ним, включая запятые, пробелы, и символы конца строки, вплоть до следующего символа (") считываются в строковую переменную; • если первый символ не является символом ("), то следующий пробел, запятая или символ конца строки заканчивают строку. Символ табуляции не является пробелом. Строкова переменная Считывается согласно указанной длине. фиксированной длины Переменная типа Variant Первый непустой символ файла начинает значение переменной. Если в файле прочитана пустая строка, то переменной присваивается значение пустой строки. Символы формата дата-время, LotusScript считывает в переменную с типом Variant(Data/Time). При считывании значения Null переменной присваивается значение Null. При невозможности определить тип переменной в файле, LotusScript формирует переменную, типа String. Для всех используемых платформ, LotusScript вставляет символ "\п" в любую многостроковую переменную. При печати этот символ трактуется как символ перевода строки. Т.о. при чтении таких данных из файла последовательного доступа, предпочтительнее использовать Input, а не Line Input. Также, при чтении данных из файла произвольного доступа, предпочтительнее использовать Get вместо оператора Input #. Пример. Файл с именем DATA.TXT открывается для записи в него данных. После закрытия файла, он снова открывается для чтения из него данных. Данные считываются из файла и выводятся на печать. Dim fileNum As Integer, empNumber As Integer, i As Integer Dim fileName As String, empName As String Dim empLocation As Variant ~" ' Dim empSalary As Currency .. .. . .^ fileNum% = FreeFile() file.Name$ = "DATA.TXT" '" " ' . _ . . . . - . Open fileName$ For Output As fileNum% ' Write #fileNum%, "Joe Smith", 123, "1 Smith Road", 25000.99 Write #fileNum%, "Jane Doe", 456, "Two Cambridge Center", 98525.66 Write #fileNum%, "Jack Jones", 789, "Fourth Floor", 0 Close fileNum% : Open fileName? For Input: As fileNum% ' • For i% = 1 To 3 Input #fileNum%, empName$, empNumber%, empLocation, empSalary@ Print ernpName$, ernpNumber%, empLocation, empSalary@ Next i% • © InterTrust Co. Тел. (095) 9567928 298 Язык LotusScript 'Выводит следующие группы значений, которые содержат значения типа 'String, Integer, Variant, ё Currency. 'Joe Smith 123 I Smith Road 25000.99 'Jane Doe 456 Two Cambridge Center 98525.66 'Jack Jones 789 Fourth Floor . 0 Close fileNum% Оператор Line Input # Line Input #fiIeNumber , varName Считывает строку из файла последовательного доступа в переменную типа String или Variant. #fileNumber - номер, присваиваемый файлу при его открытии. Символ # должен предшествовать номеру файла. varName - переменная, типа String или Variant, в которую считывается строка из файла. Оператор Line Input # считывает символы из файла последовательного доступа пока не встретит символ "перевод строки", который Line Input # не считывает в переменную. При считывании "многостроковой" строки из файла последовательного доступа используется оператор Input #, а не Line Input #. Пример. Вывод содержимого файла C:\CONFIG.SYS Dim text As String, fileNum As Integer fileNum% = FreeFile() Open "C:\CONFIG.SYS" For Input As fileNum% Do While Not EOF(fileNum%) Line Input #1, texts Print. textS 'Печать одной строки из CONFIG.SYS Loop Close fileNum% Операторы Lock и Unlock Lock [#]fileNumber [, recordNumber { [ start ] To end } J Unlock [#]fileNumber [, recordNumber | { [ start ] To end } ] Обеспечивают блокирование/разблокирование доступа к данным файлов. fileNumber - номер, назначенный файлу при его открытии. recordNumber - для файла произвольного доступа является номером записи, доступ к которой блокируется/разблокируется; для двоичного файла является номером байта, доступ к которому блокируется/разблокируется. Первая запись в файле произвольного доступа - это запись номер 1; первый байт в двоичном файле - это байт номер 1. LotusScript блокирует/разблокирует доступ только к определенной записи или байту. Для файла последовательного доступа блокируется/разблокируется доступ ко всему файлу, независимо от значения, содержащегося в recordNumber. start To end - для файла произвольного доступа это диапазон номеров записей, к которым блокируется/разблокируется доступ (аналогично, для байтов двоичного файла). Если предложение start пропущено, LotusScript определяет режим доступа в диапазоне от начала файла до значения, указанного в позиции end. Независимо от указанного диапазона, для файлов последовательного доступа LotusScript устанавливает режим доступа для всего файла. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 299 Пример. Создание записи с номером recNum% в файле произвольного доступа с именем DATA.TXT. В качестве номера открываемого файла используется первый свободный номер, значение которого получено с помощью функции FreeFileQ. Затем, файл открывается и созданная запись, модифицируется. Исходная и измененная записи выводятся на экран. Type PersonRecord empNumber As Integer einpName As String * 20 End Type Dim reel As PersonRecord, rec2 As PersonRecord Dim fileNum As Integer, recNum As Integer Dim fileName As String recNum.% = 1 fileNum% = FreeFileU fileName$ = "DATA.TXT" Open fileName$ For Random As fileNumo reel.empNumber% = 123 reel.empName$ = "John Smith" Put IfileNum, recNum%, reel Print reel.empName$ ; reel.empNumber% 'Выводит John Smith 123 'Открытие и изменение записи. Lock #fileNum%, recNum% Get #fileNum%, recNum%, rec2 Print rec2 . empName$ ; rec2.. empNuraber% 'Выводит John Smith 123 rec2.empName$ = "John Doe" Put #fileNurn%, recNum%, rec2 Print rec2.empName$ ; rec2.empNumber% 'Выводит John Doe 123 Unlock #fileNum%, recNum% - ' Close fileNum% ... • - ' - . • Оператор Open (открыть файл) Open fileName [ For { Random Input Output Append | Binary } ] [ Access { Read | Read Write | Write }] [ { Shared | Lock Read | Lock Read Write | Lock Write } ] . As [#]fileNumber [ Len = recLen ] . . . . . . . ^ : . Открывает файл для чтения/записи данных. Т.к. этот оператор должен быть записан одной строкой, то при необходимости нужно использовать символ продолжения строки -символ подчеркивания ( _ ). fileName - строковое выражение, определяющее открываемый файл. Оно может включать в себя полный путь к файлу. Если специфицированный файл не существует, то для режима Input LotusScript вырабатывает ошибку; для других режимов LotusScript создает пустой файл и открывает его. For mode (режим) - опция, значение которой определяет режим доступа к файлу; по умолчанию открывается файл произвольного доступа. Random - режим по умолчанию. Определяет режим произвольного доступа к файлу. В таком файле данные существуют в виде записей и доступ к ним осуществляется по номеру записи. Для чтения данных из файла используется оператор Get, для записи данных в файл используется оператор Put. Если предложение Access пропущено, LotusScript пытается открыть файл в одном из трех режимов: доступ в режиме Read Write, затем в режиме Write и, © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 301 файл, потому, что длина записи в файле последовательного доступа не фиксирована. Большой объем внутреннего буфера для файловых дисковых операций увеличивает их скорость. По умолчанию размер буфера равен 512 байт. • Для файлов Binary опция recLen игнорируется. Если файл открыт, как Binary, Random, или Input, то данные из него могут быть скопированы в открытый файл с другим номером. Если файл открыт, как Append или Outpute, он должен быть закрыт прежде, чем будет открыт другой файл для его копирования. Пример. LotusScript вводит данные файла c:\123w\work\thenames.txt в массив RecType. RecType тип, определенный пользователем, c:\123w\work\thenames.txt содержит следующие значения: '"Maria Jones", 12345; '"Roman Minsky", 23456; '"Joe Smith", 34567; '"Sal Piccio", 91234. Type RecType empId As Double employee As String End Type Dim arrayOfRecs() As RecType Dim txt As String Dim fileNum As Integer Dim counter As Integer Dim countRec As Integer fileNum% = FreeFile()counter?; = 0 ' ' Open "c:\123w\work\thenames.txt" For Input As fileNum% Do While Not EOF(fileNum%) Line Input #fileNum%, txt$ counter% = counter% + 1 Loop Seek fileNum%, 1 ReDim arrayOfRecs(1 To counter%) For countRec% = 1 To counter%; Input #fileNum%, arrayOfRecs(countRec%).employee$, _ arrayOfRecs (countRec%) . empId# Next Close fileNum% Print arrayOfRecs( 2 ) .employee$ & " " arrayOfRecs(2).empld# 'Выводит: 'Roman Minsky 23456 Оператор Print (вывод данных) Print [ exprList ] Выводит данные на экран (в строку состояния). exprList - список выражений, разделенных точкой с запятой, пробелом или запятой. Если пропущено exprList, оператор Print выводит пустую строку. Для вставки пробелов или символов табуляции между выводимыми элементами данных используются функции Spc и Tab. Оператор Print добавляет символ "перевод строки" (возврат каретки) в конце списка exprList, если в конце списка нет запятой или точки с запятой. LotusScript вставляет символ '\n" в любую "многостроковую" строку (например, строчный блок, заключенный в фигурные скобки). Для всех используемых платформ этот знак интерпретируется как символ "перевод строки". Следующая таблица демонстрирует, как оператора Print "реагирует" на тип данных, определенных в списке exprList. © InterTrust Co. Тел, (095) 9567928 Язык LotusScript 302 Выводится Элемент данных Переменная Значение переменной Строка Строка Дата-время Variant/Empty Строка, соответствующая в используемой платформе формату Short Date и Time. Если одна из частей выражения дата-время отсутствует, то выводится только та. которая присутствует в выражении. Пустая строка ("")• Variant/Null Строка #Null#. Следующая таблица демонстрирует действие разделителей точки с запятой и запятой на вывод элементов списка exprList. Знак пунктуации Действие Точка с запятой или пробел Точка с запятой в конце списка Запятая Следующий элемент списка выводится "вплотную" к предыдущему элементу. Следующий оператор Print продолжает выводить данные в ту-же строку "вплотную" к предыдущему элементу. Следующий элемент списка выводится в следующую позицию (зону) табуляции (они следуют одна за другой; длина такой зоны 14 символов). Следующий оператор Print продолжает вывод в ту-же строку в следующую позицию табуляции. Запятая в конце списка Пример. Dim a As Integer, b As Integer, с As Integer a% = 5 b% = 10 c% = 15 Print. a%, b%, c% 'Выводит 5 10 15 ч Оператор Print # (вывод данных) Print #fileNumber ,[ exprList ] Выводит данные в текстовый файл последовательного доступа. fileNumber - номер файла, назначаемый ему при его открытии. Элементы: #, fileNumber(номep файла) и запятая являются обязательными. exprList - опция, являющаяся списком строковых и/или числовых выражений, разделенных точкой с запятой, пробелом или запятой. При отсутствии списка exprList оператор Print # выводит пустую строку. Максимальная длина выводимой строки равна 32 К символов. Оператор Print # используется только для файлов, открытых в режимах Output или Append. В отличие от оператора Write #, оператор Print # не выводит такие форматирующие символы, как запятая и двойные кавычки. Для вставки между выводимыми элементами пробелов или табуляций используются функции Spc и Tab. Если для установки ширины строки используется оператор Width, то запятая, использованная в качестве разделителя выводного списка, перемещает позицию вывода в © InterTrust Со. Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 303 следующую позицию табуляции. Если такое перемещение выходит за рамки установленной ширины, то следующий элемент выводится с начала новой строки. Если выводимый элемент не помещается в рамки установленной ширины строки, то, т.к. Print # не обрезает значение выводимого элемента, элемент никуда не выводится. Однако, если такой элемент заканчивается символом "перевод строки", то он выводится сначала следующей строки. Следующая таблица демонстрирует определенными в списке exprList. работу оператора Print # с элементами, ••-'.• Элемент данных Действие Переменная Значение переменной Строка Строка Дата/время Variant/Empty Строка, соответствующая в используемой платформе формату Short Date и Time. Если одна из частей выражения дата-время отсутствуют, то выводится только та, которая присутствует в выражении. Пустая строка ("") Variant/Null Строка #Null# Следующая таблица демонстрирует действие разделителей точки с запятой и запятой на вывод элементов списка exprList. Знак пунктуации Действие Точка с запятой или Следующий элемент списка выводится "вплотную" к предыдущему элементу. пробел Точка с запятой в конце списка Следующий оператор Print продолжает выводить данные в туже строку "вплотную" к предыдущему элементу. Запятая Следующий элемент списка выводится в следующую позицию табуляции Пример. Открывается файл PrinText.txt. В файл выводятся две строки. Первая строка содержит 2 значение типа String, вторая строка содержит значение Null, значение Empty, переменную типа Integer, значение типа String, разделенные символом табуляции, после чего файл закрывается и открывается вновь для чтения. Результат чтения данных из файла представлен в последней строке примера. Dim nVar As Variant, eVar As Variant. . nVar = Null Dim fileNum As Integer '• ' • fileNum% = FreeFile() Open "PrinText.txt" For Output As fileNum% Print #fileNum%, "First line, " ; "with two String items" Print #fileNum%, nVar, eVar, fileNum%, "at next tab" Close fileNum% - . . ' . . . Dim text As String Open "PrinText.txt" For Input As fileNum% Do Until EOF(fileNuml) Line Input #fileNum%, text$ Print text$ Loop . - - '.' ''' '.;..'.•..: 1' © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 304 Close fileNum% . ..... 'Выводит: 'Первая строка: два элемента типа String '#Null# I at next tab Оператор Put (вывод данных) Put [#] fileNumber, [ recordNumber ], variableName Выводит значение переменной в двоичный файл или в файл произвольного доступа. fileNumber - номер, присвоенный файлу при его открытии оператором Open. Наличие знака #, номера файла fileNumber и variableName обязательно. recordNumber - опция, определяющая позицию в файле (байта в двоичном файле и записи в файле произвольного доступа), в которую выводится текущее значение переменной. Если эта опция пропущена, вывод данных осуществляется в текущую позицию открытого файла. variableName - переменная, содержащая выводимые данные. Она не может быть обычным массивом, но может быть массивом фиксированной длины, определенным внутри типа, с определенным количеством элементов. Первая запись или байт в файле имеет номер 1. После каждого выполнения операции вывода позиция вывода смещается: • для двоичного файла - на длину выводимой переменной; • для файла произвольного доступа - на длину выводимой записи. Если длина значения в переменной variableName длиннее записи, определенной в файле, то не происходит ни стирания, ни удаления уже существующей в файле записи при выводе variableName. Следующая таблица демонстрирует действия оператора Put в зависимости от типа переменной variableName. Тин variableName Действие оператора Put Variant Выводятся первые два байта значения переменной Empty или Null Данные не выводятся Числовой тип Выводится количество байтов, соответствующего числового типа: Integer - 2 байта, Long - 4 байта, Single - 4 байта, Double - 8 байт, Currency - 8 байт, Date/time - 8 байт Выводится указанное количество символов, например, для переменной, объявленной, как String * 10, будет выведено 1 0 символов Строка фиксированной длины Строка переменной длины String Вывод зависит от типа используемого файла Файл произвольного доступа: Первые два выводимых байта определяют длину выводимой строки. Оператор Put выводит соответствующее число символов. Если переменная variableName не инициализирована, то выводится строка нулевой длины. Если длина переменной variableName больше длины записи в файле, LotusScript вырабатывает ошибку. Если переменная variableName короче , чем запись, определенная в файле, то вывод производится, но О InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 305 остаток предыдущей записи, на которую наложилась выводимая запись, не стирается. Двоичный файл: Число выводимых байтов, равно длине строки, содержащейся в переменной variableName. Если значение ее не инициализировано - данные в файл не выводятся. Для типа, определенного пользователем, Put выводит суммарное количество байтов, содержащихся во всех элементах типа, кроме динамических массивов, списков или объектов. Пример. Type PersonRecord empNumber As Integer empName As String * 20 End Type -. .. . • Dim fileNum As Integer Dim fileName As String Dim rec As PersonRecord fileNuml = FreeFilet) fileNameS = "DATA.TXT" Open fileName$ For Random As fileNum% Len •-• Len(rec) rec.empNumber% = 123 rec.empName$ = "John Smith" Put #fileNum%, 1, rec 'Вывод записи в позицию 1. rec.empNumber% = 4 5 6 rec.empName$ = "Jane Doe" Put #fileNum%, 2, rec 'Вывод записи в позицию 2. rec.empNumber% = 789 rec.empName$ = "Jack Jones" Put #fileNum?i, , rec 'Вывод записи в позицию 3. 'Возврат к началу файла Seek fileNumft, 1 Do While Not EOF(fiieNuml) Get #fileNum%, , rec Print rec.empNumber%, rec.empName$ Loop 'Результат: 423 John Smith '456 Jane Doe ' 789 Jack Jones Close fileNum°o Оператор Reset Reset Закрывает все открытые файлы. Перед закрытием открытых файлов, оператор Reset выводит, при необходимости, информацию из всех внутренних буферов в файлы. Пример. Reset -. - • © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 306 Оператор Seek Seek [#]fileNumber , position Назначает в открытом файле позицию для выполне ния очередной операции ввода/вывода: для байта в двоичном файле; для записи в файле произвольного доступа fileNumber - номер, назначенный файлу при его открытии в операторе Open. position - позиция, необходимая пользователю для выполнения следующей операци и ввода или вывода данных. В двоичном файле или файле последовательного доступа это число (позиция байта) не равное 0, в файле произвольного доступа это номер записи в файле. Первый байт или первая запись имеют номер позиции, равный 1. Если задано значение позиции равное 0 или оно не задано, вырабатывается ошибка. Номер записи в операторе Get или Put неприемлемы в файле, позиция ввода/вывода в котором определена оператором Seek.. Вывод данных в позицию большую, чем позиция последнего элемента (байта или записи) файла, определяет операцию добавления данных в конец файла. Пример. Type personRecord empNumber As Integer empName As String * 20 End Type Dim reel As personRecord, rec2 As personRecord Dim fileNum As Integer, recNum As Integer-Dim fileName As String fileNum! = F'reeFile () fileName? = "DATA.TXT" recNum'^ = 5 Open fileName? For Random As fileNum% Len = Len(recl) reel.empNumbers = 123 reel.empName? = "John Smith" Print Seek (fileNum?.) 'Выводит 1 в текущую позицию файла Put #fileNura%, rec.Num%, reel 'Вывод 5-й записи в файл Print Seek ( fileNum's ) 'Выводит 6 Seek fileNum%, 1 'Возврат к 1-й записи в файле Print Seek(fileNum%) 'Выводит 1 Rec2.empNumber! = 456 Rec2.empName? = "Jane Doe" Put #fileNum%, , rec2 'Вывод данных в текущую позицию файла Print Seek(fileNum%) 'Выводит 2 Close fileNurn% Оператор Width # Width #fileNumber , width Назначает ширину (длину) строки, выводимой в текстовый файл последовательного доступа. #fileNumber - номер, присвоенный файлу в LotusScript во время его открытия; перед номером должен стоять знак #. Файл обязательно должен быть открыт. width - целое выражение, значение которого л ежит в интервале от 0 до 255 включительно, определяющее количество символов, выводимых, как одна строка, начиная с начала строки до перехода на следующую строку. По умолчанию, это значение равно 0 и определяет бесконечную по ширине строку. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 307 Если данные, выводимые обычным образом, выходят за пределы ширины текущей строки, установленной оператором Width #, эти данные выводятся в начало следующей строки. Назначение оператора Width # действительно только для оператора Print #; оператор Write # игнорирует назначение Width #. Пример. Dim fileNum As Integer Dim filename As String fileName$ = "DATA.TXT" fileNum% = FreeFile() Open Filename$ For Output As fileNum% Width #fileNum%, 20 Print #fileNum%, "First line"; Print #fileNum%, "This will go on one; line, though."; Print #fileNum%, "But. this is on another."; Print #fileNum%, "The End"; Close fileNum% Оператор Write # Write #fileNumber [, exprList ] Выводит в файл последовательного доступа любую последовательность символов. #fileNumber - номер файла, присвоенный ему при открытии. Наличие знака # перед номером обязательно. exprList - опция, являющаяся списком выражений числового типа или типа String, выводимых в файл. Элементы списка разделяются запятыми. Если предложение exprList пропущено, Write # выводит в файл пустую строку. Предложение exprList может включать массивы, списки, переменные типы или объекты, а также отдельные элементы массива, списка или типа. Оператор Write # используется только для файлов, открытых в режиме Output или Append. Для ввода данных, которые были выведены в файл с помощью оператора Write #, используется оператор Input #. Оператор Write # игнорирует в файле установку ширины линии оператором Width #. Элементы данных разделяются запятыми; символ "перевод строки" вставляется после вывода в файл любых данных. При выводе строки с продолжением, LotusScript вставляет символ "\n" (продолжение строки) в любую мультистроку. Если для вывода строки в файл последовательного доступа используется оператор Print #, символ \п для всех используемых платформ трактуется, как символ "перевод строки". При использовании для этой же цели оператора Write # символ \n интерпретируется так же, поэтому, для ввода из файла последовательного доступа мультистрок, выведенных оператором Write #, используется только оператор Input, но не Line Input. Следующая таблица показывает действие оператора Write # в зависимости от типа данных в списке exprList. , ' Тип данных Действие оператора Write # Числовой Отбрасываются пробелы впереди и сзади строки String Заключает все строки в двойные кавычки. Добавляет до необходимой длины пробелами значение фиксированной длины. Используется один из следующих форматов: #yyyy-mm-dd hh:mrn:ss# #yyyy-mm-dd# #hh:mm:ss# Variant (Date/Time) © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 308 Если отсутствует какая-либо часть выражения (определяющая дату и/или определяющая время), выводится только присутствующая часть значения. Variant, значение В файл выводится запятая. Если же пустой элемент является последним в Empty выводном списке, то запятая не выводится. Variant, значение В файл выводится строка #Null#. Null Пример. Dim Dim Dim Dim fileNum As Integer, empNumber As Integer, 1 As Integer fileName As String, ernpName As String empLocation As Variant empSalary As Currency fileNum% = FreeFile() fileName$ = "DATA.TXT" Open fileName$ For Output As fileNum% Write #fileNum%, "Joe Smith", 123, "1 Rogers Street", 25000.99 456, Write #fileNum%, "Jane Doe", "Two Cambridge Center", 98525.66 , 789, Write #fileNum%, "Jack Jones", "Fourth Floor", 0 'Чтение из файла и Close fileNum% в Open fileName$ For fileNum% ы For I% = 1 To 3 вод. Input Input. #fileNum%, As empName$, empNumber%, empLocation, empSalary@ Print empName$ empNumber%, empLocation, empSalary@ Next I% 2.8.11.3, Функции ввода/вывода Close fi .eNum% Функция EOF EOF (fileNumber) Возвращает целое значение, определяющее достижение конца файла. fileNumber - номер. идентифицирующий файл, присвоенный ему при его открытии. Возвращаемое значение зависит от типа используемого файла. Следующая таблица определяет значения функции EOF для двоичных файлов, файлов произвольного и последовательного доступа. Тип файла Двоичный Произвольный Последовательный EOF возвращает True (-1) если: EOF возвращает False(0) если: Последнее выполнение оператора Оператор Get не смог выполнить чтение затребованных номером байтов данных. Затребованная запись не может быть прочитана по причине достижения конца записей в файле Достигнут конец файла Не последнее выполнение оператора Оператор Get выполнил чтение затребованных номером байтов данных Чтение затребованной записи успешно выполнено Не достигнут конец файла Определяет достижение конца файла при чтении из него данных. Символ Ctrl+Z (ASCII код = 26) не определяет маркер конца файла любого из вышеуказанных типов. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 309 Пример. Dim text As String, fileNum As Integer fileNum's = FreeFileO Open "C:\CONFIG.SYS" For Input As fileNum! Do Until EOF(l) Line Input ttl, text$ Print text$ Loop Close fileNurr.% Функция FreeFile FreeFile Возвращает свободный номер (тип Integer) для использования при открытии файла. Функция FreeFile выдает номер файла, не являющийся номером ни одного уже открытого файла. Если все возможные номера использованы, выдается сообщение об ошибке. Всего таких номеров может быть от 1 до 255. Вызвать функцию можно в виде FreeFile или FreeFile(). Пример. Использование функции FreeFile для получения свободного номера файла. Значение номера хранится в переменной filNum%. Dim fileNum As Integer . Dim cdr As String • cdr$ = CurDriveO + "\AUTOEXEC.BAT" 'Присваивает переменной fileNum значение следующего допустимого 1 номера файла. fileNum% = FreeFile () Print FreeFileO ' Выводит 1 (1 не использован) Open cdr$ For Input Access Read As fileNum! ' Открыт файл с № 1 Print FreeFile () 'Выводит 2 (номер 1 использован) Close fileNum% " Print FreeFile () ' 'Выводит 1 (номер 1 не использован) Функция Input Input[S] ( count, [#]fileNumber ) Считывает последовательность символов из последовательного или двоичного файла в строковую переменную без каких-либо преобразований. Возвращаемое значение для функции Input - типа Variant, а для функции InputS - типа String. count - число считываемых символов (не более 32000). fileNumber - число, определяющее номер открываемого файла. LotusScript возвращает определенное число символов, начиная с текущей позиции в файле. Если количество запрашиваемых символов превышает разрешенное, возвращается максимально разрешенное количество символов. Если длина возвращаемой строки превышает значение count, выдается сообщение об ошибке. Если значение счетчика считываемых символов (count) = 0, LotusScript возвращает (""). Возвращаются все считываемые символы, включая символы "перевод строки", двойные кавычки, пробелы. При необходимости, можно получить байтовые представления символов используя функции InputB или InputB$. © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 310 Можно использовать функции Input, Input$, InputB, или InputB$ для чтения данных из файла, открытого в режиме Output, Append, или Random. Пример. - Dim fileNum As Integer Dim fileName As String Dim firstCheck As String fileNum%; = FreeFile ( ) fi1eName $ = "DATA.TXT" 'Вывод данных. Open fileName$ For Output. As fileNum% Write #fileNum%, "Joe Smith", 123, "1 Smith Road", 25000.99 Write #fileNum%, "Jane Doe", 456, "Two Cambridge Center", 98525.66 Close fileNum%'Чтение первых 23 символов и печать данных. Open fileName$ For Input As fileNum% firstCheck$ = Input$(23, fileNum%) Print firstCheck$ ' Выводит: "Joe Smith",123,"1 Smit Close fileNum% Функция InputB InputB[$] ( count, [#]fi!eNumber ) Возвращает указанное количество байтов из файлов последовательного доступа или двоичных в строковую переменную без преобразования данных. Функция InputB возвращает значение типа Variant, a InputBS - типа String. count - количество считываемых байтов (не более 64000; это количество байтов определяет 32000 символов). fileNumber - номер открываемого для чтения файла. LotusScript возвращает указанное количество байтов, начиная с текущей позиции в файле. Если количество запрошенных байтов превышает допустимое, будет возвращено допустимое количество байтов и выдано сообщение об ошибке. Количество возвращаемых символов равно половине количества возвращаемых байтов (при нечетном количестве возвращаемых байтов их число автоматически приводится к четному с помощью операции count + 1). Если count = 0, LotusScript возвращает пустую строку (""). Считываемые данные не преобразуются. Все байты вводятся без изменения, включая байты, представляющие "перевод строки", двойные кавычки, и пробел. Можно использовать функции Input, InputS, InputB. или InputBS для чтения данных из файла, открытого в режиме Output, Append, или Random. Пример. Print InputB$(4, 1) ' Выводит на печать 4 байта из файла с номером 1. Функция LOC LOC (fileNumber ) Возвращает текущую позицию в файла. fileNumber - номер, назначаемый файлу при его открытии. Следующая таблица представляет значение, возвращаемые функцией LOC для файлов произвольного доступа, последовательного доступа и двоичных файлов. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Тип файла 311 Возвращаемое значение Произвольный Номер последней записи считанной или записанной в файл Последовательный Номер позиции байта в файле, деленный на 128 и округленной до целого значения. Номер позиции последнего считанного или записанного в файл байта. Двоичный Пример. Создается произвольный файл с именем DATA.TXT и в него записываются две записи. В процессе записи контролируется длина файла. После перезаписи второй записи на место первой (удаления первой записи) длина файла уменьшается на 1. Type PersonRecord encumber As Integer empName As String *20 End Type Dim rec1 As PersonRecord, rec2 As PersonRecord Dim fileNum As Integer Dim filename As String fileNum% = FreeFile() fileName$ = "DATA.TXT" Open fileName$ For Random As fileNum%, rec1.encumber% = 123 rec1,empName$ = "John Smith" Put #fileNum%, 1, rec1 Print LOC(fileNum%) ' Выводит 1 rec2.empNumber% = 4 5 6 rec2.empName$ = "Jane Doe" Put #fileNum%, 2, rec2 Print LOC(fileNum!) ' Выводит 2 Get #fileNum%, 1, rec2 <ч. Print LOC(fileNum%} ' Выводит 1 Close fileNum% ФУНКЦИЯ LOF • . . . ; . . • ........ ,.;:'...,;•• ............................................................................. :-...;....... - :-.. :'•- ....-.•:. •,....;.-........ .......................... •....---.- LOF (fileNumber ) Возвращает длину открытого файла в байтах (тип Long). fileNumber - номер, назначенный файлу при его открытии. Функция LOF работает только с открытым файлом. Пример. Использование LOF для определения длины файла, и выполнение Input$ для чтения файла в строковую переменную izFile. Dim izFile As Integer Dim fileName As String, fileContents as String izFile% = FreeFile () tileName$ = "c:\autoexec.bat" . . . Open fileName$ For Input As izFile% fileContents$ = Input$(LOF(izFile%), izFile%) Print fileContents$ 'Вывод на экран содержимого файла ФункцияSeek .-/.•••...•-....••......•. ..... -':'•••-•,•.-..-.-. .. -'::•;-••....•..- •:•••. . .... ....•-.-:--•• Seek ( fileNumber ) Возвращает значение текущей позиции в открытом файле (позицию байта в двоичном файле и позицию записи в файле произвольного доступа). © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 312 fileNumber - номер, назначенный файлу при его открытии в операторе Open. Функция Seek возвращает значение типа Long, заключенное в интервале от 1 до 2.0Е31 -1 включительно, если номер позиции в файле не превышает этот диапазон. Для файла, в котором номер позиции превышает 2.0ЕЗО, возвращается отрицательное значение. Для двоичных файлов и файлов последовательного доступа, функция Seek возвращает значение текущей позиции байта внутри файла. Для файла произвольного доступа, функция Seek возвращает номер следующей записи внутри файла. Первый байт или первая запись в файле всегда имеют номер позиции равный 1. Пример. Type personRecord empNumber As Integer empName As String * 20 End Type Dim rec1 As personRecord, rec2 As personRecord Dim fileNum As Integer, recNum As Integer Dim fileName As String fileNum% = FreeFile() fileName$ = "DATA.TXT" recNum% == 5 Open fileName$ For Random As fileNum"; Len = ben (reel) reel.empNumber% = 123 reel.empNameS = "John Smith" Print Seek(fileNum%) 'Выводит 1 в текущую позицию файла Put #fileNum!, recNum%, reel 'Вывод 5-й записи в файл Print Seek ( f ileNurn% ) 'Выводит 6 Seek fileNum!, 1 .'Возврат к 1-й записи в файле Print Seek(fileNum%) 'Выводит 1 Rec2.empNumber% = 456 Rec2.empName$ = "Jane Doe" Put #fileNum%, , rec2 'Вывод данных в текущую позицию файла Print Seek(fileNuml) 'Выводит 2 Close fileNum% Функция Tab Tab ( column ) 7 При вызове из операторов Print или Print # функция Tab выводит в текущую позицию указанное количество символов. column - любое числовое выражение в интервале значений от 1 до 32000 включительно, определяющее количество позиций вывода. Даже если значение column меньше 1, по умолчанию функция Tab установит ее в 1 (левая граница вывода). Если определена ширина для выводного файла, функция Tab проверяет значение column на соответствие этой ширине и выполняет следующее: • если вывод производится уже за пределами установленной ширины, функция Tab выводит символ "перевод строки" и продолжает вывод оставшихся символов в следующую строку; • если количество символов, определенное значением column, помещается в текущую позицию, функция Tab выводит необходимое количество символов, начиная с указанной позиции в текущую строку. Если вывод производится в строку, ширина которой установлена с помощью оператора Width #, функция Tab выполняет следующее: © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 313 Tab выводит Column > ширины column Mod width <1 column 1 < текущей позиции вывода (column - текущая позиция) следующая строка > текущей позиции вывода (column - текущая позиция)) та же строка Пример. Выводится содержимое переменных firstN и iastN. Функция Tab() используется для разделения следующих элементов: Bob Jeremiah, Jeremiah, Jeremiah, Jeremiah. Точка с запятой в операторе Print является опцией; знак не влияет на формат вывода, если позиции вывода определяются с помощью Tab. Dim firstN As String, firstN$ = "Bob" IastN As String lastN$ = "Jeremiah" Print firstN$; Tab (5); lastN$; Tab (1) ; last.N$; Tab (2); lastN$; _Tab(3); lastN$ 2.8.12. Работа с OLE-объектами Основные положения Концепция связи и встраивания объектов (OLE - Object Linking and Embedding), обеспечивает текущему приложению доступ к данным других приложений, включая возможность их использования и, при необходимости, изменения. OLE-объект - группа определенных данных, например, текст, графика, звук и вообще все, что отображается и поддерживается каким-либо приложением - OLE-сервером. Любое другое приложение, поддерживающее протокол OLE - OLE-клиент - может обращаться к данным OLE-объекта. OLE-объект может быть или связан с использующим его приложением (сам OLE-объект в этом случае хранится отдельно от приложения, а приложение "знает", где он хранится), или встроен в текущее приложение (OLE-объект "хранится" в самом приложении). И в том и в другом случае приложение -клиент может получить доступ к данным OLE-объекта. . . . : Функция CreateObject CreateObject ( className ) Создает OLE-объект и возвращает ссылку на него. className - строка типа Variant, удовлетворяющая спецификации вида appName.appClass и определяющая тип создаваемого объекта, например, "WordPro.Document". appName - имя приложения, которое поддерживает OLE-объект. appClass - класс создаваемого OLE-объекта (одно приложение-сервер может поддерживать OLE-объекты нескольких классов). Если приложение-сервер еще не выполняется, то CreateObject запускает его, чтобы создать OLE-объект. Оператор Set присваивает возвращаемое функцией CreateObject значение ссылки переменной типа Variant. Ссылка на OLE-объект является допустимой только во время выполнения поддерживающего его приложения. Если это приложение завершается, а OLE-объект не сохранен, LotusScript возвращает ошибку периода выполнения. LotusScript поддерживает OLE-коллекции оператором ForAll. Поддерживаются и "параметрические" свойства OLE-объектов. Например, если OLE-объект, ссылку на который © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 314 "хранит" переменная v, имеет свойство Prop с двумя аргументами, чтобы присвоить этому свойству значение 4, нужно "записать": v . prop (argl, arg2) = 4 Пример. Создание документа Word Pro, вставка в него строки текста и сохранение документа в файле. StyleSheet, Insert, Save - свойства и методы OLE-объекта класса Document, поддерживаемого сервером (текстовым процессором) WordPro. ; _..... Dim myDoc As Variant Set myDoc = CreateObject("WordPro.Document") myDoc - StyleSheet, = " basic, sty" myDoc.Insert = myText$ myDoc.save "c:\mydocs\" & fileName$ Функция GetObject .. :. .. .. . GetObject ( pathName [, className ] ) Открывает OLE-объект и возвращает ссылку на него. pathName - строка, содержащая полный путь и имя файла OLE-объекта или пустая строка. Если задана пустая строка, то должна быть определена строка className. className - строка вида appName.appCIass, определяющая приложение, в котором создан OLE-объект, и класс этого OLE-объекта. Например, "WordPro.Document". Возвращаемая функцией GetObject ссылка на OLE-объект присваивается переменной типа Variant оператором Set. Если приложение, специфицированное, как appName, не выполняется, функция GetObject запускает его. Ссылка на OLE-объект "имеет силу" только во время выполнения поддерживающего его приложения. Если это приложение незапланированно завершается, LotusScript: выдает ошибку периода выполнения. Если pathName указано пустой строкой (""), функция GetObject пытается найти любой текущий активный объект специфицированного класса. Если такой объект не найден -выдается ошибка. Пример. Файл c:\status.sam загружается в редактор WordPro (как в приложение-сервер). Оператор Set присваивает переменной myDoc ссылку на OLE-объект. К OLE-объекту применяется метод Print -документ печатается. Dim myDoc As Variant ' Получение ссылки на OLE-объект из файла Set myDoc = GetObject("с:\status.sam", "WordPro.Document") ' Вызов метода Print, определенного для объекта класса WordPro.Document myDoc.Print 2.8.13. Синхронизации работы параллельно выполняемых Web-агентов Типичной реализацией выполнения серии операций в базе данных при взаимодействии Domino-приложения с Web-пользователем являются Web-агенты. Начиная с версии Domino 4.5.1 возможно параллельное исполнение Web-агентов. Каждый Web-агент исполняется в отдельном потоке серверного процесса HTTP. Если на сервере не разрешено одновременное (асинхронное) выполнение нескольких Web-агентов, то они выполняются последовательно (serialized). Это приводит к тому, пользователь может долго ждать результата простой операции в случае, если более сложную (длительную) операцию раньше запросил другой пользователь. Параллельное (asynchronous) исполнение Web-агентов позволяет достичь оптимального времени отзыва системы, адекватного © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @гформулы, LotusScript, встроенные классы LotusScript и Java 315 сложности операции и зависящего от количества пользователей, но не от очередности обращения пользователей. В примере в таблицах видно, что параллельное исполнение агентов приводит к относительно небольшому увеличению времени работы агента 1 (сложного) и в то же время к ощутимому уменьшению времени реакции системы на запрос пользователя В (простой агент 2). Последовательное исполнение агентов: Момент времени Операция Комментарий Пользователь А инициирует запуск агента 1 0 1 Вычисления Стартует агент 1 . Пользователь В инициирует запуск агента 2 2 Вычисления Выполняется агент ! 3 Вычисления Выполняется агент 1 4 Вычисления Выполняется агент 1 5 Вывод результата Завершает работу агент 1 6 Вычисления Стартует агент 2 7 Вывод результата Завершает работу агент 2 Параллельное исполнение агентов: Момент времени Поток 1 Поток 2 Комментарий Пользователь А инициирует запуск агента 1 0 1 Вычисления Стартует агент 1 , Пользователь В инициирует запуск агента 2 2 Вычисления Выполняется агент 1 3 Вычисления Агент 1 приостанавливается. Стартует агент 2 4 Вывод результата Завершает работу агент 2 5 Вычисления Выполняется агент 1 6 Вычисления Выполняется агент 1 7 Вывод результата Завершает работу агент 1 © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 316 Но простого разрешения параллельного исполнения Web-агентов на сервере недостаточно. Необходимо обеспечение устойчивости такой многопотоковой системы. Устойчивость многопотоковой системы предполагает: * либо отсутствие общих ресурсов потоков : либо наличие (и использование) механизмов блокировки ресурсов потоками Общим ресурсом могут быть подлежащая модификации информация в БД. Для того, чтобы избежать конфликтов необходимы механизмы синхронизации. LotusScript 4.0 (в Domino R5) такие средства синхронизации Web-агентов имеет. Этими средствами являются новые встроенные функции работы с семафорами (с терминологии документации - lock). * CreateLock - создание (подключение к) семафора * DestroyLock - уничтожение (отключение от) семафора * CodeLock - закрытие семафора * CodeUnlock - открытие семафора * CodeLockCheck - длина очереди к семафору * Sleep - приостановка работы скрипта на указанное время © Функция CreateLock CreateUnlock ( name As String ) Возвращает целочисленный идентификатор семафора (lock) с именем, заданным строкой пате. Если ссылок на семафор с таким именем до сих пор не было (например, в другом потоке), то он создаётся и ему присваивается идентификатор. Успешно полученный идентификатор является целым числом. Можно сказать больше: значение идентификатора всегда число от 0 до 255 и нельзя определить более 256 семафоров (такая попытка заканчивается ошибкой с номером 238 -«Maximum number of semaphores permitted reached»). Т.е. под хранение идентификатора используется один байт. Если переменная, хранящая значение идентификатора, оказалась за пределами области видимости, идентификатор может быть безболезненно переполучен повторным вызовом функции. Другими словами, в Web-агенте (т.е. в пределах одного потока) можно сколько угодно раз подключаться к одному и тому же семафору, например, в каждой определенной пользователем подпрограмме или функции. Имена семафоров уникальны в пределах текущей области общей памяти, т.е. для всех Web-агентов, выполняющихся в рамках задачи HTTP. При завершении работы потока все ссылки на использовавшиеся семафоры автоматически удаляются и, если нет больше ссылок, удаляется семафор. Несмотря на это правильнее удалять ссылки на семафоры явно, используя функцию DestroyLock. Если платформа не поддерживает механизм семафоров или недостаточно общей памяти, то будет возвращена ошибка. © Функция CodeLock CodeLock ( ID As Integer ) Выполняется попытка закрытия семафора с идентификатором, заданным целым числом ID. Идентификатор ID должен быть предварительно получен вызовом функции CreateLock. ©InterTrust Co. Тел. (095)9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 317 При успешном закрытии семафора функция возвращает TRUE. Другое значение означает неуспех операции. Этот исход принципиально отличается от ситуации, когда семафор уже закрыт другим Web-агентом. В этом случае выполнение Web-агента приостанавливается, как будто функция CodeLock долго не возвращает результат. В это время многопотоковая система передает управление следующему Web-агенту и т.д. Таким образом, образуется очередь агентов, пытающийся закрыть один и тот же семафор и все «ждут» пока семафор не откроется. Попытка закрыть семафор с неизвестным идентификатором (ссылка на семафор не была создана вызовом CreateLock или уже была удалена вызовом DestroyLock) приводит к возникновению ошибки с номером 235 - «Lock ID has not been created». Любой семафор, закрытый функцией CodeLock, обязательно должен быть открыт вызовом функции CodeUnLock. Несоблюдение этого правила приводит к непредсказуемым результатам. © Функция CodeUnLock CodeUnlock (ID As Integer ) Открывает семафор, заданный идентификатором ID. Идентификатор ID должен быть предварительно получен вызовом функции CreateLock. Открытый семафор становится доступен следующему агенту в очереди на закрытие. Любой семафор, закрытый вызовом функции CodeLock, обязательно должен быть открыт вызовом функции CodeUnLock. Несоблюдение этого правила приводит к непредсказуемым результатам. 0 Функция CodeLockCheck CodeLockCheck (ID As Integer ) Для указанного идентификатором ID семафора возвращает число агентов закрывших семафор или ожидающих своей очереди на закрытие. Другими словами, возвращается длина очереди агентов «к закрытому семафору» плюс один. Результат является целым числом. Эта функция никак не отражает число агентов ссылающихся на данный семафор (получивших с помощью функции CreateLock его идентификатор). Пример 1. Семафор «SomeLockName» закрыт неким агентом и других агентов, ожидающих его открытия, нет. Dim LickID as Integer •-•-•• LickID = CreateLock(«SomeLockName») Print CodeLockCheck(LockID) ' Печатает 1 . . - .... , Пример 2. Семафор «SomeLockName» закрыт неким агентом и есть еще один агент, запросивший закрытие семафора и ожидающий его открытия. Dim LickID as Integer LickID = CreateLock(«SomeLockName») Print CodeLockCheck(LockID) x Печатает 2 Пример З. Семафор «SomeLockName» открыт. Dim LickID as Integer LickID = CreateLock(«SomeLockName») Print CodeLockCheck(LockID) v Печатает i InterTrust Co. Тел. (095) 9567928 Я) ы к L o t us Scr i pt 318 © ФункцияDestroyLock ' •.,••.--•••/- • ! .: .::---..•:••-:'-•:.;;•;.-•;.:.•• i':.;.•••••;••..••-:•.•........ :'.;; ': ..':.'. ""• - DestroyLock (ID As Integer) ': ,^ \ . Удаляет ссылку текущего агента (т.е. потока) на указанный семафор. Если при этом общее количество ссылок на этот семафор оказывается равным нулю, то семафор удаляется (освобождается его идентификатор). Идентификатор ID должен быть предварительно получен вызовом функции CreateLock. При успешном удалении ссылки на семафор функция возвращает TRUE. Другое значение означает неуспех операции. Несмотря на то, что при завершении работы агента ссылки на использовавшиеся агентом семафоры автоматически удаляются, рекомендуется удалять ссылки на семафоры явно, используя функцию DestroyLock. Пример. Удаление ссылок агента на семафоры Dim LickID as Integer LickID = CreateLock(«SomeLockName») % Получаем Q - идент. семафора Print DestroyLock (LockID) ' Печатает True-Print DestroyLock(10) Л Ошибка № 235 - «Lock ID has not been created» © OnepaTOp'Sleep • • • ; . : TV"-.. - г - : . ........ ,.....: •....•::;:•..: . , . . . . . . . . . . ,,'........................ ;•............... Л:...'...•.:.:.............. •••......: .v Sleep ( time as Float) Приостанавливает выполнение скрипта на указанное время. Время остановки указывается в секундах дробным числом гг/ие.Приостановка выполнение скрипта с помощью этого оператора имеет принципиальные отличия и преимущества от традиционной реализации задержки в виде формального цикла: • • при задержке по оператору Sleep не занимаются вычислительные ресурсы освободившиеся ресурсы используются другим процессом • в многопоточной системе управление передается другому потоку В случае параллельного исполнения Web-агентов при приостановке одного из них управление автоматически передается следующему. Надо заметить, что реальное время задержки может оказаться и больше указанного. Это определяется загруженностью системы. •.• Минимальное время задержки определяется платформой, на которой исполняется код. Если минимальным квантом является милисекунда, то указанное дробное число будет огруглено до тысячных. Обширный пример использования оператора Sleep имеется в пункте «Пример синхронизации работы параллельно выполняемых Web-агентов» этого параграфа. Пример. На диаграмме загрузки процессора (см. ниже) хорошо видно, что при приостановке скрипта оператором Sleep системные ресурсы не занимаются. Кстати, пики загрузки процессора приходятся на формальные циклы. E'or is. = 1 То 100000 ' занимает процессорное время Next Print Now Print "-" Print Now ' выполняется моментально вслед за ' предыдущим оператором (время попросту совпадает) Print "-" Sleep ( 5 ) ' процессор не нагружается Print Now ' время отличается ровно на 5 секунд For i& = 1 То 100000 ' занимает процессорное время Next © InterTrust Co. Тел. (095) 9567928 • • Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 319 Kernel: Processor Usage (%) © Функция GetThreadlnfo GetThreadlnfo (InfoID ) Возвращает системную информацию о текущем потоке. InfoID - числовой код, определяющий вид возвращаемого показателя. Возможные значения и назначения данного кода приведены с таблице: Код Показатель LSl_THREAD_LINE Номер текущей строки LSI_THREAD_PROC Имя текущей процедуры LSI „THREAD MODULE Системное имя текущего модуля LSI_THREAD_VERS1ON Номер версии LotusScript LSI_THREAD LANGUAGE Текущие языковые настройки LSI_THREAD_COUNTRY Номер национальных настроек LSIJTHREAD TICKS Значение системного таймера LSI THREADjriCKS_PER_SEC Число квантов таймера в секунду Функция возвращает значение типа Variant, содержащее строку или число в зависимости от конкретного кода. Пример. Результат раотобы функции GetTheadlnfo на рабочей станции Notes 5.O. %INCLUDE «Isconst.Iss» Sub Initialize Print Getthreadinfo (LSI_THREAD__LINE) Print ' Выводит 4 1 Выводит INITIALIZE Getthreadinfo(LSI_THREAD_PROC) Print ' Выводит *302EED4 Getthreadinfo(LSI JTHREADJMODULE) Print 1 Выводит 4.0.0.20 Getthreadinfo(LSI_THREAD_VERSION) Print Getthreadinfo(LSI_THREAD_LANGUAGE) Print ' Выводит en Getthreadinfo(LSI_THREAD_COUNTRY) Print ' Выводит О Getthreadinfo(LSI_THREAD_TICKS) Print ' Выводит 35490733 Getthreadinfo(LSI_THREAD_TICKS_PER_ End SEC) ' Выводит 1000 Sub © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 320 Разрешение параллельного исполнения Web-агентов Для того чтобы Web-агенты выполнялись не последовательно (serialized), а параллельно (asynchronous), необходимо в файл notes.ini сервера записать строку DominoAsynchronizeAgents^l и перезапустить серверную задачу HTTP. Файл notes.ini можно (и лучше) не править напрямую, а включить соответствующую опцию в серверном документе в базе данных Domino Directory (название в предыдущих версиях - Public Address Book): Basics Security Ports Server Tasks (Internet Protocols) MTAs (HTTP)] Domino Web Engine I Run web agents Web agent timeout (in seconds) Miscellaneous Тransactional Logging Administration HOP | LDAP 1 NNTP 1 Enabled "0; Пример синхронизации работы параллельно выполняемых Web-агентов Предположим, имеется некое Domino-приложение, выполняющееся на сервере Domino, допускающем асинхронное исполнение Web-агентов. Запросы пользователей обрабатываются Web-агентами, которые выполняют критичную для многопотоковой работы операцию, например, модификацию одних и тех же данных. Во избежание конфликта агенты создают (и непосредственно перед записью блокируют) специальный флаг. Назовем его «MyUpdateLock». Таким образом, сценарий работы таков: .. • • Агент Agentl стартует, создает флаг «MyUpdateLock» и выводит об этом сообщение. Далее агент Agent 1 приостанавливает свою работу на секунду. Это сделано в примере специально для того, чтобы заведомо смог начать параллельную работу агент Agent2 (в противном случае нельзя быть уверенным в том когда именно будет переключен контекст потоков). Агент Agent2, стартовав, также создает флаг «MyUpdateLock». 7 Далее один из агентов, например Agent2, захватавает (блокирует) флаг «MyUpdateLock» и выводит об этом сообщение. Потенциально продолжительная работа агента по модификации данных в нашем примере симитирована секундной задержкой. В это время опять может (и происходит) переключение на другой поток. Но параллельный агент не может войти в критичный блок «модификации данных», так как не может захватить флаг - флаг остался занят первым агентом - и ждет (фактически, результата функции захвата флага). Контекст снова переключается. Первый агент, закончив критичную работу, освобождает (разблокирует) флаг и выводит на консоль соответствующее сообщение. В этом месте кода намеренно сделана очередная секундная задержка, — для того чтобы снова переключился контекст потоков. Это происходит. Агент, пытающийся захватить флаг, наконец, его получает и так далее. В нашем примере захват-освобождение флага повторяется в цикле 5 раз. Option Public Option Declare Sub Initialize Dim ID as String, lockName As String Dim lockID As Integer, refcnt As Integer, i as Integer Dim gotLock As Variant, releaseLock As Variant,_ cieleteLock As Variant On Error Goto syn _error © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 321 ' Присваиваем агенту имя (чтобы идентифицировать вывод) ID = "Agent I " Msgbox ID & "Started" ! iockName = "MyUpdateLock" , ' Создаем флаг lockID = Createlock(IockName) If (lockID <> -1) Then Msgbox ID & "Created lock: " & lockID End If ' Делаем задержку в одну секунду 1 Это позволит запуститься второму агенту. Sleep 1 For i = 1 То 5 . - • 1 Пытаемся захватить флаг, сообщаем об этом ' а также сообщаем длину очереди на захват флага gotLock = CodeLock(lockID) If (gotLock) Then Msgbox ID & "Got: lock: " & lockID & " - at: " & Now () refcnt = Codelockcheck(lockID) Msgbox ID & " Reference count is " & refcnt ' Выполняем критичную работу. Для простоты просто ' создаем задержку в одну секунду Sleep 1 - " Else Msgbox ID & "Failed to get lock" End If . ' Освобождаем флаг. Другой агент теперь может его захватить releaseLock = Codeunlock(lockID) If (releaseLock) Then Msgbox ID & "Releasing lock: " & lockID & " - at: " & Now() ' Делаем задержку для того, чтобы другой агент мог захватить ' флаг прежде, чем данный агент снова его захватит Sleep 1 Else . .. Msgbox ID & "Failed to release lock" End If Next ' Критичная работа завершена. Отключаемся от флага. deleteLock = DestroyLock(lockID) If (deleteLock ) Then Msgbox ID & "Destroyed lock " & lockID Else Msgbox ID & "Failed to destroy lock" End If ... Msgbox ID & "Done" Exit Sub . -• syn error: errormsg = " * * Error: " & Err & " - " & Error() & _ " ~, С* r-\ 1 U " itГ Т PidL Г " 6: -~ Г 41.. " Г.1Г ( Vj -к- Т I \ J-. П Msgbox errormsg Resume Next End Sub - - .. ' Так выглядит вывод на консоль сервера наших агентов: 09.06.99 13:16:04 Addin: Agent message box: Agentl Started 09.06.99 13:16:04 Addin: Agent message box: Agentl Created lock: 0 © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 322 09.06.99 13:16:04 Addin: Agent message box: Agent2 Started 09.06.99 13:16:04 Addin: Agent message box: Agent2 Created lock: 0 09.06.99 13:16:05 Addin: Agent message box: Agent2 Got lock: 0 - at: 09.06.99 13:16:05 09.06.99 13:16:05 Addin: Agent message box: Agent2 Reference count is 1 09.06.99 13:16:06 13:16:06 Addin: Agent message box: Agent:2 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:06 Addin: Agent message box: Agent1 Got lock: 0 - at: 09.06.99 13:16:06 09.06.99 13:16:06 Addin: Agent message box: Agent 1 Reference count is 1 09.06.99 13:16:08 13:16:08 Addin: Agent message box: Agent 1 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:08 Addin: Agent message box: Agent2 Got lock: 0 - at: 09.06.99 13:16:08 09.06.99 13:16:08 Addin: Agent message box: Agent2 Reference count is 1 09.06.99 13:16:09 13:16:09 Addin: Agent message box: Agent2 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:09 Addin: Agent message box: Agent 1 Got lock: 0 - at: 09.06.99 13:16:09 09.06.99 13:16:09 Addin: Agent message box: Agent 1 Reference count is 1 09.06.99 13:16:10 13:16:10 Addin: Agent message box: Agent 1 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:10 Addin: Agent message box: Agent2 Got lock: 0 - at: 09.06.99 13:16:10 09.06.99 13:16:10 Addin: Agent message box: Agent2 Reference count is 1 09,06.99 13:16:11 Addin: Agent message box: Agent 1 Got lock: 0 - at: 09.06.99 13:16:11 09.06.99 13:16:11 13:16:11 Addin: Agent message box: Agent2 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:11 09.06.99 13:16:12 Addin: Agent message box: Agent1 Reference count is 1 Addin: Agent message box: Agent 1 Releasing lock: 0 - at: 09.06.99 13:16:12 09.06.99 13:16:12 Addin: Agent message box: Agent2 Got lock: 0 - at: 09.06.99 13:16:12 09.06.99 13:16:12 Addin: Agent message box: Agent2 Reference count is 1 09.06.99 13:16:13 13:16:13 Addin: Agent message box: Agent2 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:13 Addin: Agent message box: Agent 1 Got lock: 0 - at: 09.06.99 13:16:13 09.06.99 13:16:13 09.06.99 13:16:14 Addin: Agent message box: Agentl Reference count is 1 Addin: Agent message box: Agentl Releasing lock: 0 - at: 09.06.99 13:16:14 09.06.99 13:16:14 Addin: Agent message box: Agent2 Got lock: 0 - at: 09.06.99 13:16:14 09.06,99 13:16:14 Addin: Agent message box: Agent2 Reference count is 1 09.06.99 13:16:15 13:16:16 Addin: Agent message box: Agent2 Releasing lock: 0 - at: 09.06.99 09.06.99 13:16:15 Addin: Agent message box: Agent! Got lock: 0 - at: 09.06.99 13:16:16 09.06.9913:16:15 © InterTrust Co. Тел. (095) 9567928 Addin: Agent message box: Agentl Reference count is 1 Lotus Domino R. 5.- @-формулы, LotusScript, вст^^енные классы LotusScript u Java 09.06.9913:16:17 Addin: Agent message box: Agent2 Destroyed lock 0 323 ^ ^ 09.06.9913:16:17 Addin: Agent message box: Agent2 Done ^^ ^ ^ 09.06.99 13:16:17 Addin: Agent message box: Agent 1 Releasing lock: 0 - at: 09.06.99 13:16:17 09.06.9913:16:18 Addin: Agent message box: Agent 1 Destroyed lock 0 09.06.9913:16:18 Addin: Agent message box: Agentl Done 2.8.14. Обработка ошибок в LotusScript 2.8.14.1. Основные положения При разработке скрипта ошибки могут возникнуть как на этапе создания скрипта, так и на этапе его выполнения. Соответственно этому ошибки делятся на две группы: • ошибки периода компиляции; * ошибки периода выполнения. - * - - : - ., : Ошибки периода компиляции Могут появляться во время обработки компилятором LotusScript исходного текста скрипта. Ошибка компиляции останавливает процесс компиляции. При наличии ошибки необходимо проанализировать синтаксис операторов скрипта и, после исправления ошибки, запустить повторно процесс его компиляции. , , Ошибки периода выполнения Могут возникать во время выполнения скрипта. Ошибки периода выполнения скрипта отражают нарушения условий выполнения и не могут быть обнаружены на этапе его компиляции. Примерами ошибок периода выполнения могут служить, например, ошибка, связанная с попыткой открыть для чтения несуществующий на диске файл, или ошибка, связанная с попыткой использования в качестве делителя переменной, значение которой к моменту выполнения этой операции равно нулю. Ошибки периода выполнения останавливают выполнение скрипта, если пользователем в тексте программы не предусмотрены "ловушки ошибок", т.е. специальные операторы, к которым происходит обращение при появлении соответствующей ошибки. LotusScript идентифицирует большинство ошибок периода выполнения и выдает соответствующие сообщения о них. Можно вставить в скрипт свои процедуры обработки ошибок периода выполнения, которые будут идентифицировать возникающие ошибки, выдавать соответствующие сообщения, а при необходимости, и обеспечивать продолжение выполнения скрипта. Номера ошибок Каждая ошибка периода выполнения имеет свой собственный номер, однозначно идентифицирующий ее. Когда во время выполнения скрипта возникает ошибка, LotusScript, "зная" номер ошибки, ищет соответствующий ей оператор On Error. Если оператор имеется, дальнейшая обработка ошибки проистекает в соответствии с этим оператором. Например, при возникновении ошибки с номером 357 можно воспользоваться следующим оператором -"ловушкой", передающим управление на метку. On Error 357 GoTo аросбОО . .-.-..;•.- © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 324 .•.••-•-•-.: Большинство ошибок периода выполнения уже предопределены в LotusScript. Файл LSERR.LSS содержит константы, значениями которых являются номера ошибок периода выполнения. При создании скрипта можно включить в него этот файл с помощью директивы fe; %Include "LSERR.LSS". Можно также задать номера для "пользовательских" ошибок. Сигнал о том, что случилась "пользовательская ошибка", обычно "подается" оператором Error номер_ошибки. Если для пользовательской ошибки предусмотрен оператор On Error, он получает управление. Например: Const ooBounds = 677 ..... . . . ' Определяет номер "пользовательской" ошибки ' Этот номер выходит за рамки существующей спецификации ошибок г On Error ooBounds ... ' что делать при возникновении ошибки i Error ooBounds ' сигнал о возникновении ошибки • Обработка ошибок периода выполнения Итак, при выполнении скрипта возникает ошибка. Это или предопределенная ошибка, обнаруженная внутренними средствами LotusScript, или "пользовательская ошибка", сигнал о которой "подал" сам разработчик скрипта. В любом случае известен номер ошибки. LotusScript проверяет текущую процедуру на наличие в ней оператора On Error n, где n -номер ошибки. Если оператор On Error n не найден, проверяется наличие оператора On Error, не связанного с номером конкретной ошибки. Если такие операторы не найдены, LotusScript продолжает их поиск в процедуре, вызвавшей текущую, и т.д. Если не найдено соответствующего оператора On Error, выводится сообщение об возникшей ошибке и выполнение прекращается. Если же соответствующий оператор On Error найден, то, если в On Error указан оператор Resume Next, продолжается выполнение той процедуры, в которой возникла ошибка, с оператора, следующего за оператором, при выполнении которого возникла ошибка. Если оператор On Error определяет переход на метку (Goto метка), то выполнение продолжается с оператора, помеченного этой меткой. Если в качестве метки указан О, повторяется выполнение вызвавшего ошибку оператора. т Далее следует описание операторов, реализующих функции идентификации и обработки ошибок. 2.8.14.2. Операторы обработки ошибок Оператор Err (установить номер ошибки) Err = errNumber Устанавливает номер текущей ошибки. Параметр errNumber - числовое выражение, значение которого является номером ошибки. Номер может принимать любое значение из диапазона от 0 до 32767 включительно. Оператор Error (установить номер и сообщение об ошибке) Error errNumber [, msgExpr ] Устанавливает номер ошибки и соответствующее ей сообщение. Параметр errNumber -числовое выражение, значением которого является номер ошибки, определенной в © InterTrust Co. Тел, (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 325 LotusScript или определенной пользователем. Аргумент errNurnber может принимать любое значение из диапазона от 1 до 32767 включительно. Параметр msgExpr - строковое выражение, содержащее сообщение об ошибке. Это строковое выражение замещает любое существующее сообщение, соответствующее ошибке с данным номером. Если значением errNumber является ошибка, определенная в LotusScript, то оператор Error фиксирует ошибку LotusScript. Иначе фиксируется ошибка, определенная пользователем. Если для данной ошибки не предусмотрена обработка (нет оператора On Error), выдается соответствующее сообщение об ошибке. Это сообщение может быть определено в параметре msgExpr. Если параметр msgExpr отсутствовал, LotusScript выдает свое сообщение, соответствующее данному номеру ошибки, если таковое существует. В противном случае выдается сообщение об ошибке, определенной пользователем. Оператор On Error (реакция на ошибку) On Error [ errNumber ] { GoTo label Resume Next GoTo 0 } Определяет реакцию на ошибку, возникшую в период выполнения скрипта. Параметр errNumber - выражение, значением которого является целое число, задающее номер ошибки. При отсутствии этого параметра оператор описывает реакцию на любую ошибку, возникающую в текущей процедуре во время выполнения. Оператор GoTo label определяет адрес передачи управления при возникновении ошибки с указанным номером. Обычно, это подпрограмма обработки ошибок. Оператор Resume Next определяет, что при возникновении ошибки выполнение процедуры должно продолжаться с оператора, следующего за оператором, в котором возникла ошибка. В этом случае не инициируется функция обработки ошибок. Оператор GoTo 0 определяет, что при возникновении ошибки не будет происходить ее обработка. Пример. При возникновении деления на нуль получает управление оператор On Error. В его теле имеется оператор Resume Next, передающий управление на следующий оператор за тем, в котором возникла ошибка. Если действительно имело место деление на нуль (номер ошибки равен константе ErrDivisionByZero, определенной в файле LSERR.LSS), печатается сообщение, и функция завершается. ^Include "LSERR.LSS" Function Best (} Dim x As Integer, у As Integer, On Error Resume Next i y% = 3 z% = 0 ' z As '* Integer х% = у% / z% ' Ошибка деления на ноль If Err = ErrDivisionByZe.ro Then Print "Attempt to divide by 0. Returning to caller." Exit Function End If . • •• t End Function Call Best ( ) Оператор Resume Resume [ 0 | Next | label ] Определяет, куда следует передать управление после обработки ошибки: © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 326 • 0 - управление получает оператор, в котором возникла ошибка; • Next - управление получает оператор, следующий за оператором, в котором возникла ошибка; • label - управление получает оператор, помеченный меткой label. Учтите, что если причины возникновения ошибки в процедуре обработки ошибки не были устранены, оператор Resume [0] породит бесконечный цикл. Оператор Resume устанавливает в 0 значение функций Err, Erl, Error. Пример. Оператор Error сигнализирует об ошибке. Получает управление обработчик ошибки (метка ErrHandler). После печати сообщения обработчик передает управление на следующий оператор за тем, в котором возникла ошибка - в данном случае на следующий оператор Error. Sub ResumeSubO On Error GoTo ErrHandler Error I Error 10 Error 100 Exit Sub ErrHandler: Print "Error " & Err & " at line number" &Erl Resume Next End Sub 2.8.14.3. Функции обработки ошибок ФункцияErl ...•-•••.•• ;•• '.;:.-•••.: :••••••• •-.- • ••• -••• ••- . .- :......,-.•• .-."."• Erl Возвращает номер строки (тип Integer) в тексте скрипта, в операторе из которой возникла ошибка. Если ошибки нет, возвращается значение False (0). Пример. Выводит 0, поскольку нет ошибки. Sub RepErr Dim x As Integer x% = Erl () Print x% End Sub Call RepErr Функция Err ...... •'.-....-••.••..• ••-.•••••.••:••-. • . . •• . . . . • . . . . • . . . . . . •..... :.. Err Возвращает номер текущей ошибки (тип Integer). Если ошибки нет. возвращается значение False (0). Функция Error Error[S] [ ( en-Number ) ] Возвращает сообщение об ошибке с номером errNumber, либо, если номер не указан, сообщение о последней имевшей место ошибке. Функция Error возвращает значение типа © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 327 Variant, а функция Error$ - типа String. Если отсутствует выражение errNumber и нет текущей ошибки, функция возвращает пустую строку(""). Пример. Пользователь вводит число, значение которого должно находиться в диапазоне 1 - 100. Если введенное значение не может быть приведено к 4-х байтовому целому значению, то выдается ошибка. Определены и две пользовательские ошибки при выходе за диапазон значений 1 - 100. Public x As Single Const TOO_SMALL = 1001, TOO_BIG = 1002 Sub GetNum Dim Num As String On Error Goto Errhandle Num$ = InputBox$("Enter a value between 1 and 100:") 'Преобразование строки 4-байтное single значение x! = CSng (Num$) • •-. ' Проверка введенного значения If x! < 1 Then Error TOO_SMALL, "Значение меньше допустимого" ElseIf x! > 100 Then Error TOO_BIG, "Значение больше допустимого" End If 'Вывод сообщения при отсутствии ошибок ввода MessageBox "Хорошая работа! " & Num$ & " Введено правильно." Exit Sub ' При наличии ошибок выводится номер ошибки и сообщение Errhandle: 'Функция Err возвращает номер ошибки 'Функция Error$ возвращает диагностическое сообщение MessageBox "10ёаёа" & Str(Err) & ": " & Error$ Exit. Sub End Sub ' GetNum ' Вызов подпрограммы GetNum • • • © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 328 2.9. Вызов внешних функций из библиотек динамической • компоновки Основные положения » LotusScript поддерживает возможность вызова внешних функций, написанных обычно на языке С и размещающихся в библиотеках функций. В терминах WINDOWS такая библиотека функций называется библиотекой динамической компоновки - DLL (Dinamic Link Library). При работе с внешними С-функциями необходимо знать их интерфейсы (виды аргументов, вид возвращаемого функцией значения) и собственно назначения функций. Для получения этой информации может потребоваться соответствующая документация. Если говорить о функциях WINDOWS, то документация по Windows API входит в состав Windows Software Developer's Kit. Кроме того данной теме посвящено множество книг. DLL чаще пишут на языке С, хотя последнее необязательно. В любом случае внешние функции должны удовлетворять следующим соглашениям по вызову: « WINDOWS 3.1 (Winl6)-Pascal, • WINDOWS 95, 98 и WINDOWS NT (Win32) - STDCALL, • OS/2 - _System • UNIX и Macintosh - соответствующее CDECL. Вызываемая из LotusScript внешняя функция обязательно должна быть предварительно объявлена в скрипте. Аргументы во внешнюю функцию могут передаваться по ссылке или по значению. На платформе Win32 (WINDOWS 95, 98 и WINDOWS NT) следует помнить, что имя функции, экспортируемой DLL, чувствительно к регистру. Пример. Объявляется внешняя функция из библиотеки C:\myxports.dll. Библиотека экспортирует эту функцию под именем HelpOut (с учетом регистра). Из LotusScript функцию будут вызывать по имени DirDLL (уже без учета регистра). Функция имеет два скалярных параметра, оба типа Long. Параметры передаются ссылкой. DirDLL(5, 10) - уже пример вызова этой функции. ' Объявление Declare Function DirDLL Lib "C:\myxports.dll" Alias "_HelpOut" (II As Long, 12 As Long) ' Вызов DirDLL;5, 10) Объявление С-функций Любую С-функцию необходимо объявить прежде, чем она будет вызвана. Объявление выполняется с помощью специальной формы оператора Declare. Оператор Declare следует помещать в область Declarations модуля, внутри которого предполагается вызов (или вызовы) С-функции. В операторе Declare вы можете объявить С-функцию либо как функцию LotusScript, либо как подпрограмму. Синтаксис таков: Declare [Public | Private] {Function | Sub} LSFunctionName Lib libNaine [Alias aliasName ) ( [ argList ] ) [ As return Type ] © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5; @-формулы, LotusScript, встроенные классы LotusScript и Java 329 Если С-функция не возвращает результата или результат вас не интересует, то имеет смысл объявлять С-функцию как подпрограмму LotusScript. В противном случае - как функцию LotusScript. Проиллюстрируем сказанное с помощью примеров. Рассмотрим функции находящиеся в библиотеке User Windows API. Функция GetActiveWindow не требует параметров и возвращает дескриптор (целое число) активного окна (окна, имеющего фокус). Declare Function GetActiveWindow Lib "User" () As Integer Функция SetWindowText ничего не возвращает, поэтому вы можете декларировать её как процедуру. Функция требует два параметра: дескриптор окна и текстовую строку. В оригинале имена обоих параметров удовлетворяют требованиям к идентификаторам LotusScript. Поэтому при декларации функции можно использовать оригинальные имена параметров, взяв их из документации по API (как сделано в примере), а можно ввести новые, собственные имена. Declare Sub SetWindowText Lib "User" (ByVal hWnd As Integer, _ ByVal IpString As String) Оператор Declare (объявление внешних С-функций) Declare f Public | Private ] { Function | Sub } LSname Lib libName &. [Alias aliasName ] ( [ argList ] ) [ As return Type ] Объявляет внешние С-функции, содержащиеся в библиотеке функций, в качестве функций или подпрограмм, вызываемых из LotusScript. Public | Private - по выбору. Необязательно. Public определяет, что С-функция доступна в LotusScript за пределами модуля, в котором она объявлена, пока этот модуль находится в памяти. Private определяет, что С-функция доступна только внутри модуля, содержащего ее объявление. По умолчанию С-функция считается Private. Function | Sub - определяют способ вызова С-функции из LotusScript: как функцию или как подпрограмму. LSname - имя функции или подпрограммы, используемое в LotusScript. Если оператор объявляет функцию (использовано ключевое слово Function), к LSname можно добавить суффикс, определяющий тип возвращаемого функцией значения. Если спецификатор Alias опущен, это имя должно совпадать с именем С-функции в библиотеке функций. Для платформы Win32 существенно сохранение оригинального регистра написания имени функции. Lib libName - задается строка символов или символьная константа, специфицирующая имя файла библиотеки функций. Стандартное расширение необязательно. Необязательно и указание пути к файлу. Alias aliasName - задается строка символов или символьная константа, содержащая одно из следующих: * с учетом регистра, имя С-функции, как оно объявлено в библиотеке функций. • число с префиксом #, определяет положение (позицию) функции в библиотеке функций; например, # 1. © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 330 Этот спецификатор полезно использовать в том случае, если имя С-функции не является допустимым именем в LotusScript или попросту для того, чтобы сделать имя функции в скрипте более простым для восприятия. argList - список аргументов внешней функции, заключенный в круглые скобки. Скобки должны использоваться даже в том случае, если функция не имеет аргументов. Аргументы в списке разделяются запятыми, а каждый аргумент имеет формат: [ By Val ] name As [ LMBCS | Unicode ] [ dataType Any ] Если указано ключевое слово ByVal, то аргумент передается по значению, иначе по ссылке. Необязательные ключевые слова LMBCS или Unicode могут использовать только для аргументов типа String. DataType определяет тип аргумента. Ключевое слово Any используют, когда аргумент должен передаваться в С-функцию без проверки типа. As returnType имеет формат As [ LMBCS | Unicode ] dataType и определяет тип возвращаемого функцией значения. Этот спецификатор не используется для С-функции, вызываемой как подпрограмма. Для функций использую! или явную спецификацию As returnType, или суффикс, определяющий тип возвращаемого функцией LSname значения, но не оба варианта вместе. В качестве типа возвращаемого значения не должны использоваться Any, Variant, Currency или String фиксированной длины. Если тип возвращаемых данных не указан явно и в имени вызываемой функции нет суффикса, считается, что функ ция возвращает значение типа согласно оператору описания типа DefT'ype для используемого имени функции. Учтите, что тип dataType должен точно соответствовать типу возвращаемого С-функцией значения - LotusScript не производит над возвращаемым значением каких-либо преобразований типа. Ключевые слова LMBCS или Unicode могут использоваться только тогда, когда функция возвращает значение типа String. Передача аргументов. По умолчанию LotusScript передает аргументы во внешнюю функцию по ссылке. Чтобы передавать аргументы по значению, следует указать в описании аргумента ключевое слово ByVal. Однако это возможно только тогда, когда LotusScript может привести передаваемое значение к типу данных аргумента С-функции. Массивы, переменные определенных пользователем типов или объекты объявленных пользователем классов могут передаваться только по ссылке. В С-функцию нельзя передать (ни по значению, ни по ссылке) список. Объекты встроенных классов "представлены" четырехбайтовым дескриптором объекта (instance handle), который может быть передан в С-функцию как по значению, так и по ссылке. Для организации передачи объекта по значению аргумент должен быть явно описан с использованием ключевого слова ByVal. Использование круглых скобок при передаче фактического значения объекта не допускается Параметр может быть объявлен как Any (любой), чтобы избежать ограничений, накладываемых типом данных. Параметры "типа Any" всегда передаются ссылкой, независимо от их действительного типа. Используя Any, вы, в принципе, можете передать в С-функцию даже значение типа Variant, содержащее ссылку на массив или список. Вопрос только в том, "понимает" ли С-функция данные этого типа. Подробнее о передаче аргументов С-функции рассказано ниже в отдельных разделах. Использование LMBCS или Unicode. Ключевые слова LMBCS или Unicode применяются только для аргументов или возвращаемых функцией значений типа String. Они определяют способ кодировки символов в строке. Unicode означает кодировку Unicode (2 байта на символ) с использованием зависящего от платформы порядка байтов. LMBCS означает кодировку LMBCS фирмы Lotus (несколько байтов на символ, английские буквы кодируются одним байтом, русские - двумя байтами, а символы японских, корейских и китайских "алфавитов" - гремя байтами). Если ни LMBCS, ни Unicode не указаны, предполагается, что символы в строке кодируются в соответствии с текущим способом кодировки на используемой платформе. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 331 Пример 1. Объявление и вызов внешней функции StrUpr, содержащейся в библиотеке StrLib. Dim strOut As String 'Объявление StrUpr Declare Function StrUpr Lib "StrLib" 'Вызов StrUpr strOutS = StrUpr ("abc") •••••-• (ByVal inVal As String) As String Пример 2. Объявление и вызов С-функции _SendExportedRoutine (имя с учетом регистра), экспортируемой библиотекой C:\myxports.dll, как внешней функции SendDLL в LotusScript. Declare Function SendDLL Lib "C: \myxports.dll" Alias "_SendExportedRoutine" (il As Long, 12 As Long) 'Вызов SendDLL SendDLL( 5 , 10) Пример З. Объявление функции StrFun, получающей в качестве параметра amlStr строку в кодировке Unicode и возвращающей строку в кодировке Unicode. Declare Function (amlStr As StrFun Unicode Lib String) "lib.dll" As Unicode String Пример 4. Объявление функции StrFun, получающей в качестве параметра amlStr строку в кодировке LMBCS и возвращающей строку в текущей кодировке используемой платформы. • Declare Function StrFun Lib "lib.dll" (amLStr As LMBCS String) As String . Пример 5. Вопроизведение звука средствами Windows API Declare Function sndPlaySound Lib "winmm" Alias "sndPlaySoundA" (ByVal IpszSoundName As String, ByVal uFlags As Long) As Long Const SYNC =1 Dim res Res = sndPlaySound("ohoh", print Res ' SYNC) . ' . _ ' • • • • ' " ' • .• Передача аргументов по ссылке При передаче аргумента по ссылке из LotusScript в С-функцию последняя получает в стеке 4-х байтовый указатель на фактическое значение параметра в памяти LotusScript. Правда, в некоторых случаях фактический параметр указывает только на "публично читаемую структуру", не предоставляя доступа к закрытым данным. Однако во всех случаях С-функция может изменить доступные ей "по указателю" данные, и эти изменения произойдут в значениях переменных в LotusScript и в свойствах объектов встроенных классов, как только управление вернется в LotusScript. Следующая таблица поясняет, как параметры ссылкой передаются из LotusScript в С-функцию. Тип данных LotusScript Что передается в С-функцию String 4-х байтовый указатель на строку во внутреннем формате строк LotusScript Array 4-х байтовый указатель на массив во внутреннем формате массивов LotusScript © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 332 Объект встроенного класса (включая коллекцию) 4-х байтовый дескриптор (handle) объекта Стандартный или определенный пользователем тип 4-х байтовый указатель на данные этого типа Определенный пользователем объект 4-х байтовый указатель на члены-данные в объекте этом Передача аргументов по значению Вообще говоря, при передаче аргументов по значению С-функция получает в стеке копию текущего значения аргумента. По умолчанию аргумент во внешнюю функцию из LotusScript передается ссылкой. Поэтому всякую передачу по значению следует специфицировать явно. Можно в операторе Declare явно указать для каждого передаваемого по значению аргумента ключевое слово ByVal - тогда при вызове функции из LotusScript соответствующие параметры всегда будут передаваться по значению. Можно указать только при конкретном вызове внешний функции из LotusScript, что некоторые параметры передаются по значению - такие параметры записывают в круглых скобках или перед ними указывают ключевое слово ByVal. Следующая таблица поясняет, как параметры по значению передаются из LotusScript в Сфункцию. . . . . . . . Тип данных Какие данные передаются в С-функцию 2-х байтовое целое, записываемое в стек lЈM_^___1 значение типа Long, записываемое в стек Single 4-х байтовое значение типа Single, записываемое в стек Double 8-и байтовое значение типа Double, записываемое в стек Currency 8-и байтовое значение во внутреннем формате LotusScript, записываемое в стек String 4-х байтовый указатель на первый символ строки, записанный в стек. Это уже не классическая передача по значению, поскольку С-функция может изменить информацию в строке-параметре. С-функция не должна изменять информацию в памяти "за пределами" строки. Variant 16-и байтовая структура во внутреннем формате LotusScript, записываемая в стек 4-х байтовый дескриптор объекта, записанный в стек Объект встроенного класса Any Записанное в стек значение передаваемого параметра текущей длины. Например, при одном обращении параметр может быть типа Integer, и будут переданы 2 байта. При другом обращении параметр может иметь тип Long, и будут переданы 4 байта. В результате затруднится разработка С-функции, поскольку во время компиляции неизвестно, какого типа параметры она получит. Integer Другие типы данных: массивы, списки, строки фиксированной длины, переменные определенных пользователем типов или объекты определенных пользователем классов- не могу! передаваться в С-функцию по значению. Однако их (кроме списков) можно передать по ссылке. Обратите внимание, что список нельзя передать в С-функцию ни по значению, ни по ссылке. © InterTrust Co. Тел. (095) 9567928 Lotas Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 333 Если аргумент внешней функции объявлен в операторе Declare с типом Any, и должен передаваться по значению, при вызове функции следует передаваемый параметр специфицировать как By Val. Наконец, когда аргумент объявлен с типом Any, а параметр при вызове передается как ByVal &0, С-функция получает "нулевой" указатель. Пример. С-функция SemiCopy получает 4-х байтовый указатель на двухбайтовое целое значение переменной vTestA, и двухбайтовое значение - копию значения переменной vTestB. Поскольку первый аргумент передается по ссылке, С-функция может изменить значение переменной vTestA в LotusScript, "записывая по указателю" наподобие *ptr = newValue. В то же время С-функция не может изменить значение переменной vTestB в LotusScript. Declare Sub SemiCopy Lib "mylib.dll" _ (valPtr As Integer, ByVal iVal As Integer) Dim vTestA As Integer, vTestB As Integer vTestA = 1 vTestB = 2 ' вызов SemiCopy vTestA, vTestB ' ' ' ' Передача строк из LotusScript в С-функцию Когда строка передается по ссылке, LotusScript передает 4-х байтовый указатель на эту строку в "своей" памяти. При этом С-функция не может безопасно модифицировать содержимое этой строки, если только она не написана специально для LotusScript (для этого требуется знание внутренних форматов строк LotusScript). Когда строка передается по значению, С-функция получает 4-х байтовый указатель на копию строки LotusScript - "заканчивающуюся нулем строку", как это принято в языке С. Если передается строка фиксированной длины, она сначала преобразуется в "заканчивающуюся нулем строку". При этом С-функция может изменять данные в строке, но не должна изменять длину строки. Когда С-функция завершается, изменения, внесенные ею в копию строки, будут перенесены в соответствующую ей строку в формате LotusScript. Если символы в передаваемой или возвращаемой строке заданы не в текущей кодировке используемой платформы, а в кодировке Unicode или LMBCS, это должно быть специфицировано явно. Следующая таблица суммирует поведение строковых параметров при передаче в С-функцию. В таблице предполагается, что С-функция имеет имя cF и один строковый аргумент. Первый столбец содержит два возможных способа объявления этого аргумента в операторе Declare: либо передача по значению, либо ссылкой. Второй и третий столбцы показывают, что передается в С-функцию в зависимости от использованного способа ее вызова из LotusScript (второй - по значению, а третий - по ссылке). Объявление Если функция cF вызывается Если функция cF вызывается строкового из LotusScript в форме: из LotusScript в форме: аргумента в _,„ , , ,, „, , CF ( ( arg ) ) cF ( arg ) операторе Declare СCF ( ByVal ( arg )) cF ( ByVal arg ) функции cF ByVal String 4-х байтовый указатель на 4-х байтовый указатель на копию значения фактического значение фактического параметра. Если функция cF параметра. Если функция cF изменяет данные по этому изменяет данные по этому указателю, значение указателю, изменяется и фактического параметра не значение фактического ' InterTrust Co. Тел. (095) 9567928 Язык LotusScript 334 меняется. Если функция cF параметра. Если функция cF "пишет" за границами "пишет" за границами полученной строки, возможен полученной строки, возможен крах LotusScript. крах LotusScript, String 4-х байтовый указатель на 4-х байтовый указатель на копию значения фактического значение фактического параметра во внутреннем параметра во внутреннем формате строк LotusScript. Если формате строк LotusScript. Если функция cF изменяет данные по cF "не знакома" с этим этому указателю, значение форматом, она может лишь фактического параметра не заменить ссылку на эту строку меняется. ссылкой на другую (но корректную) строку. Передача из LotusScript в С-функцию массивов, переменных определенных пользователем типов и объектов определенных пользователем классов Передать массив в С-функцию можно только по ссылке. Но массивы в LotusScript хранятся в собственном внутреннем формате. При этом С-функция "должна понимать" внутренний формат массивов LotusScript. Авторы не встречали в документации подробного описания этих форматов. В некоторых простых случаях можно объявить в операторе Declare аргумент, по которому должен передаваться массив, с "типом" Any, а в качестве значения фактического параметра передать по ссылке первый элемент массива. Пример 1. Третий аргумент функции SetBitmapBits объявлен с "типом" Any, а при вызове функции по третьему аргументу передается ссылка на первый элемент этого массива. Declare Sub SetBitmapBits Lib "_privDispSys" (ByVal hBM As Integer, ВуVal cBytes As Long, pBits As Any) SetB itmapB its(hB itmap, cB ytesInA rra y, bi tA rray(O ) ) Передать в С-функцию значение переменной определенного пользователем типа можно тоже только по ссылке. При этом С-функция получит 4-х байтовый указатель непосредственно на первый байт соответствующих данных в LotusScript. В простых случаях этого бывает достаточно, чтобы "добраться" до необходимых элементов данных. В более сложных случаях опять возникнут проблемы, связанные с "незнанием" внутренних форматов некоторых типов данных LotusScript. Отметим, что если в определенном пользователем типе в качестве элементов присутствуют строки переменной или фиксированной длины (но не Variant типа String), для указания способа кодировки символов во всех строках "внутри типа" в операторе Declare можно использовать ключевые слова Unicode или LMBCS. Если ни Unicode, ни LMBCS не указано, строки в определенном пользователем типе передаются в текущей кодировке используемой платформы. Пример 2. В первом операторе Declare все строки переменной или фиксированной длины в типе tl и его вложенных типах передаются как строки Unicode, а во втором - как строки LMBCS. Declare Function UniTest Lib "Unilib" (typArq As Unicode tl) As Long Declare Function LMBCSTest Lib "Imbcslib" (typArg As LMBCS tl) As Long Обратите также внимание, что LotusScript в целях обеспечения межплатформной совместимости выравнивает некоторые элементы типа иначе, чем это принято по умолчанию в компиляторе С на используемой платформе. Например, для типа с определением © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Type telMet • . - • • • A As Integer В As Integer End Type • v • • '. - 335 •••.-:-. ... LotusScript выравнивает элемент В на четырехбайтовую границу, тогда как выравнивание по умолчанию в Windows 3.1 выполняется на двухбайтовую границу. Пример 3. С-функции GetBrushOrgEx вторым аргументом передается определенный пользователем тип Point. Type Point хР As Integer уР As Integer End Type Declare Function GetBrushOrgEx Lib "__pointLib" _ (ByVal hDC As Integer, pt As Point) As Integer Dim p As Point GetBrushOrgEx(hDC,p) Когда в С-функцию передается объект определенного пользователем класса, С-функция получает 4-х байтовый указатель на первый байт неупакованных данных объекта. В случае простых объектов до их данных "удается добраться" сравнительно легко. Но для сложных объектов, содержащих внутри списки, массивы, строки или объекты встроенных классов, это может оказаться трудноразрешимой задачей. Значение, возвращаемое С-функцйей в LotusScript ;;; •. у-... :: • •.::: ;••; '•. •> /• ••:;::-::: ••••;: :^\;::•'•;:::-;:::.: •., Тип возвращаемых С-функцией данных должен быть указан одним из следующих способов: • в операторе Declare явно, • в операторе Declare с использованием суффикса, г • на основе оператора Deftype, предшествующего оператору Declare. Если ничто из перечисленного не имеет места, по умолчанию в LotusScript будет предполагаться, что функция возвращает значение типа Variant, тогда как этот тип несовместим с языком С. Следующая таблица показывает, данные каких типов могут быть возвращены С-функцией в LotusScript. Тип данных Может ли быть возвращен С-функцией Integer Да Long Да Single Да Double Да Currency Нет String Variant в LotusScript? Да, за исключением строки фиксированной длины Нет © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 336 Объект встроенного класса Да (как 4-х байтовый дескриптор объекта (handle) типа Long) Объект определенного пользователем класса Да Переменная определенного пользователем типа Нет Any Нет Array Нет List Нет Пример. Функция GetWindowsDirectory входит в состав API Windows. Функция определяет каталог, в котором на текущем компьютере установлен Windows. Путь на каталог в форме строки записывается по указателю, передаваемому функции первым аргументом. Вторым аргументом задается максимальное количество байтов, которое функции "разрешается записать" по этому указателю. Возвращает же функция действительное количество байтов, которое ею было записано по указателю. Обратите внимание, что функция не записывает по указателю байт с нулевым кодом, являющийся в языке С традиционным признаком конца строки. Этот пример проверялся под Windows NT 3.51 и Windows 98. Библиотека, в которой находится функция, называется Kernel32.dll. Внутреннее имя функции с учетом регистра в этой библиотеке GetWindowsDirectoryA, а не GetWindowsDirectory, под которым она традиционно экспортируется. В скрипте объявлена строка фиксированной длины WinDir, в которую вызываемая внешняя функция заносит путь на каталог. Все параметры передаются во внешнюю функцию по значению. Уже после вызова функции, чтобы избежать проблем с длиной строки, она "корректируется по месту" функцией Mid$ LotusScript. CONST MAX_DIR_SIZE = 255 ' DIM WinDir AS STRING*MAX_DIR_SIZE DIM ActLen AS INTEGER Declare Function GetWindowsDirectoryA Lib "Kernel32" (ByVal IpBuffer As String, ByVal nSize As Integer) 1 MAX_ DIR_SIZE - максимальная длина буфера 'ActLen - текущая длина пути на каталог ActLen = GetWindowsDirectoryA ( WinDir, MAX_DIR_SIZE ) WinDir = mid$(WinDir,1,ActLen) Print WinDir As Integer • -...-, т 'Печатает D:\WINNT351 При создании собственных библиотек С-функций Если вы используете компилятор C++, то следует учитывать искажение имен функций. В этом случае при написании собственных С-функций следует использовать конструкцию "С" {. . . } для сохранения точного имени. Символ "-" зарезервирован в Notes для специальных библиотек. Эта особенность впервые появилась в версии 4.5.1. В версии 4.5.1 и старше (в том числе и 5.x) при попытке загрузки в скрипте библиотеки (dll) с именем начинающимся с "-" выдается ошибка "Error in loading DLL". Под значение типа Integer в LotusScript отводится 2 байта. В тоже время на платформе Win32 (Windows 95, 98, Windows NT) значение типа Integer занимает 4 байта. Поэтому, если разрабатываемая вами С-функция должна вернуть в LotusScript значение типа Integer, О InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 337 следует внутри С-функции использовать тип Short Integer, использующий 2 байта. Это замечание относится исключительно к реализации под Windows. Пример импорта строки текстового файла Предположим имеется задача чтения в скрипте русского текста из текстового файла в кодировке 866. Эта операция выполняется с помощью стандартных LotusScript средств ввода-вывода. Но прежде, чем строка станет «пригодной для использования» в Windows необходимо выполнить её перекодировку из кодировки 866 в кодировку 1251 (сама операция чтения строки из файли никакой перекодировки не производит). Для этого используетс я функция Window s A PI " O emToA nsi". Скрипт в нашем примере оформлен в виде агента. Так в разных поколениях Windows местоположение необходимой нам функции различно, объявляется сразу две функции. Declare Function OemToAnsi32 Lib "User32" Alias "OemToCharA" (Byval IpOemStr As String, Byval IpAnsiStr As String) As Integer Declare Function OemToAnsi16 Lib "Keyboard" Alias "OemToAnsi" _ (Byval IpOemStr As String, Byval IpAnsiStr As String) As Integer Function OemToAnsi(IpOemStr As String, IpAnsiStr As String) As Integer Dim Session As New NotesSession ' В зависимости от версии Windows 1 вызывается та или иная С-функция If session.Platform = "Windows/32" Then OemToAnsi = OemToAnsi32(IpOemStr, IpAnsiStr) Elseif session.Plat form = "Windows/16" Then OemToAnsi = OernToAnsil6 (IpOemStr, IpAnsiStr) End If End Function Sub Initialize Dim tfile%, res% Dim Stroka$ tf.ile% = Freefile() Open «c:\dos_file.txt» For Input As tfile% Line Input #tFile%, Stroka$ л переменная Stroka$ получает значение f)r&6GE© в^ббв res% = OemToAnsi(Stroka$, Stroka?) print Stroka$ * петается Русский текст End Sub . • Пример. Замена оператору SendKeys Как известно, оператор SendKeys не поддерживается в реализации LotusScript для Lotus Notes. Но благодаря имеющимся в LotusScript средствам обращения к внешним С-фукциям задачу решить можно (по частному мнению автора этих строк, вряд ли «фирменная» реализация оператора была бы устроена по-другому). Данный прим ер публикуется с лю безного согласия его автора - Андрэ Гайрарда (Andre Guirard) , сотрудника американской компании Systems Consulting Group, inc. 'SendKey script library: Option Public Option Declare © InterTrust Co. Тел. (095) 9567928 Язык LotusScript 338 %REM Данная библиотека содержит функции для имитации ввода символов с клавиатуры. Библиотека рассчитана на работу в среде Win32 Поддержка платформ Winl6 и OS/2 может быть достигнута путем использования других (соответствующих) библиотек (DLL). Функции операционной системы, выполняющие основную работу, взяты из стандартных DLL и описаны, например, в документации к Visual Basic. Данная библиотека включает следующие функции: Sub SetKeyState(byval bVk As Integer, byval onoffstate As Integer) где bVk - код клавиши с состояниями "вкл." и "выкл." (соотв. значения True и False) Функция устанавливает состояние одного и таких ключей, например Call SetKeyState(VK SCROLL, False) выключает клавишу [Scroll Lock] Sub PressKey(Byval vk As Integer) где vk - код клавиши. Эта функция посылает ОС код клавиши для имитации ее нажатия и отпускания. Например, Call PressKey(VK_Fn + 3) эквивалентно нажатию клавиши [F3]. Функция ориентирована на клавиши, для которых нет "непечатного" аналога Sub HoldKey(byval vk As Integer) Данная функция посылает ОС код клавиши, для которой нужно симитировать нажатие и удержание в нажатом состоянии Sub ReleaseKey(byval vk As Integer) Данная функция "отпускает" ранее "нажатую" с пом.ощыо функции HoldKey клавишу. Например, если мы хотим передать последовательность [Alt]+[Enter], то необходимо произвести следующие вызовы: HoldKey VK MENU PressKey VK_RETURN ReleaseKey VK_MENU Sub SendKey(Byval c$) Печатает символ. Данная функция предназначена для упрощенного "нажатия" клавиш, у которых есть "печатные" аналоги. Например, цифры, буквы и т.п. Sub SendString(Byval s$) Имитирует ввод целой строки. Фактически выполняет серию вызовов функции SendKey %END REM Const VK_MENU = &Н12 ' [Alt] Const VK RETURN = SHOD Const VK JLEFT = &H25 Const VK UP = &H26 Const VK_RIGHT = &H27 Const VK_DOWN = &H28 Const VK_TAB = &H09 Const VK_SHIFT = &H10 Const VKJCONTROL = &H11 Const VK_ESCAPE = &H1B Const VK_SCROLL = &H91 © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5: @~формулы, LotusScript, встроенные классы LotusScript и Java Const Const Const VK_Fn = &H6F 339 VK_CAPITAL = &H.14 VK_NUMLOCK &H90 ' Функциональные клавиши; для получения кода 1 конкретной клавиши надо добавить ее номер, ' например, VK_Fn+3 для [F3] Const KEYEVENTF_KEYUP - &Н2 ' код для "отпускания" клавиши Dim CapsLock% Declare Sub keybd_event Lib "user32" Int eger , (Byval bVk As Integer, Byval bScan As Byval dwflags As Long, Byval dwextrainfo As Long) Declare Sub mouse_event Lib "user32" (Byval dwflags As Long, Byval dx As Long, Byval dy As Long, _ Byval cbuttons As Long, Byval dwextrainfo As Long) Declare Function OemKeyScan Lib "user32" (Byval wOemchar As Integer) As Long Declare Function CharToOem Lib "user32" Alias "CharToOemA" (Byval IpszSrc As String, Byval IpszDst As String) As Long Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" (Byval cChar As Integer) As Integer Declare Function MapVirtualKeyS Lib "user32" Alias "MapVirtualKeyA" (Byval wCode As Long, wMapType As Long) Declare Function GetKeyState% Lib "user32" (Byval virtkey&) Declare Sub GetKeyboardState Lib "User32" (LpKeyState As Any) Declare Sub SetKeyboardState Lib "User32" (LpKeyState As Any) Sub SendString(Byval s$) CapsLock = ((1 Arid GetKeyState (VK _CAPITAL) ) <> 0) Dim i% For i = 1 To Len(s) SendKey Mid$(s, i, 1) Next End Sub Sub PressKey(Byval vk As Integer) Dim scan% ' получаем scan code данной клавиши scan = MapVirtualKey(vk, 1) And &HFF keybd_event vk, scan, 0, 0 ' "нажимаем" клавишу keybd_event vk, scan, KEYEVENTF_KEYUP, 0 ' "отпускаем" клавишу End Sub Sub HoldKey(Byval vk As Integer) Dim scan% ' получаем scan code данной клавиши scan = MapVirtualKey(vk, 1) And &HFF keybd_event vk, scan, 0, 0 ' "нажимаем" клавишу End Sub Sub ReleaseKey(Byval vk As Integer) Dim scan% ' получаем scan code данной клавиши scan = MapVirtualKey(vk, 1) And &HFF keybd__ event vk, scan, KEYEVENTF_ KEYUP, 0 Sub - ' "отпускаем" клавишу End Sub SetKeyState(Byval bVk As Integer, Byval onoffstate As Integer) © InterTrust Co. Тел. (095) 9567928 340 Язык LotusScript ' Исп. для активации и деактивации клавиш Caps Lock, Mum Lock, or Scroll Lock. Dim a%(0 To 127), ind%, mask* GetKeyboardState a(0) ind = bVk \ 2 If (bVk And I) Then ' windows хранит впереди младший байт; если индекс четный - нужен бит 1 .mask -= 1 • Else-mask = &hOlOO End If. ' Теперь, если необх. режим не явл. текущим, ' now, if the desired state doesn't match the existing state, меняем бит активности и переписываем состояние If ((a(ind) And mask) <> 0) о onoffstate Then a find) = a(ind) Xor mask SetKeyboardState a(0) End If End Sub Sub SendKey(Byval c$) Dim vk%, scans, oemchar$, dl&, shifted*, scanshift* ' получаем виртуальный код данного символа vk = VkKeyScan(Asc(c$)) And &HFF oemchar = " " ' Иниуиализируем строку на необходимую длину CharToOem Left$(c$, 1), oemchar dl = OEMKeyScan(Asc(oemchar)) scan = dl And &HOOOOFFFF& If (c$ >= "a" And c$ <= "z") Or . (c$ >- "A" And c$ <= "Z") Then shifted = ((c = Ucase(c)) Xor CapsLock) Else shifted = (dl And &H00030000&) > 0 End If If shifted Then scanshift = MapVirtualKey(VK_SHIFT, 1) keybd_event VK_SHIFT, scanshift, О, О End If keybd_event vk, scan, О, О keybd_event vk, scan, KEYEVENTF KEYUP, 0 If shifted Then keybd_event VK_SHIFT, scanshift, KEYEVENTF_KEYUP, 0 End If End Sub © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 341 2.10. Ограничения языка В новой версии LotusScript 4, использующейся в Notes/Domino R5, по сравнению с предыдущей версией (LotusScript 3 -Notes/Domino R4) сняты некоторые ограничения. Среди них такие как органичение на размер исполняемого кода модуля, ограничение на размер динамической строки. Большинство ограничений традиционно объединяют под общим названием «ограничения 64К байт». Все наиболее существенные ограничения далее рассматриваются отдельно. - 2.10.1. Ограничения числовых типов данных Тип данных Диапазон допустимых значений Объем занимаемой памяти Integer от -32,768 до 32,767 2 байта Long от -2, 1 47,483,648 до 2, 1 47,483,647 4 байта Single . от -3.402823Е+38 до 3.402823Е+38 4 байта Double от -1 .797693 1348623 1 58+308 до 1.7976931348623158+308 8 байт Currency от -922,337,203,685,477.5807 до 922,337,203,685,477.5807 8 байт String Ограничено доступной памятью 2 байт на символ Диапазон допустимых значений двоичных, восьмеричных и шестнадцатиричных целых чисел совпадает с диапазоном типа Long. Следующая таблица описывает максимальное число символов, необходимых для отображения соответственно двоичных, восьмеричных и шестнадцатиричных значений. Одновременно эта же таблица описывает максимальное число символов, которое могут вернуть функции Bin< Oct и Hex. Целый тип Максимальное число символов, необходимых для значения Двоичный 32 Восьмеричный 11 Шестнадцатиричный 8 отображения © InterTrust Со. Тел. (095)9567928 Язык LotusScript 342 2.10.2. Ограничения строковых данных Ограничения на представление строк: Показатель : Notes версий 4.x Общее число строк Notes версий 5.x Ограничено только доступной Ограничено только памятью доступной памятью Ограничено только Общий объем строковых Для модуля в целом 32К доступной памятью данных в модуле символов (64К байта). Для динамических строк - строк, получающих значение во время исполнения скрипта -ограничено только доступной памятью Длина строкового литерала 16,267 символов (32,000 байт). 16,267 символов (32,000 байт). Длина строки 2 G байт 32,000 символов (64,000 байт) Общий объем строковых литералов в модуле 2 G байт Несмотря на то, что в LotusScript 4 строки могут быть длинее 64К, остаются ограничения на длину строк, которые могут быть прочитаны или записаны с использованием операторов GET и PUT. Строки фиксированной длины, переменные типа Variant, содержащие строки и файлы произвольного доступа не работают со строками длиннее 64К. Более длинные строки могут использоваться в двоичных файлах и строках переменной длины. Причина состоит в том, что все они имеют 2-х байтный заголовок, задающий длину строки. Двумя байтами нельзя описать большую длину, чем 64К. 2.10.3. Ограничения на массивы Показатель Объем данных массива Notes версий 4.x 64К байта Число измерений Notes версий 5.x Ограничено только доступной памятью 8 8 Размерности измерений от -32,768 до 32,767 (представляется значением типа Integer) от -32,768 до 32,767 (представляется значением типа Integer) Число элементов Определяется объемом доступной памяти и размером отдельного элемента массива (различен для разных типов данных). Определяется объемом доступной памяти и размером отдельного элемента массива (различен для разных типов данных). © InterTrust Со. Тел. (095) 9567928 LotHS Domino R. 5: ^формулы, LotusScript, встроенные классы LotusScript и Java 343 Ограничение на число элементов массива обусловленно предельным объемом скалярных данных на уровне модуля. Это 64К, Так, одноразмерный массив типа Long, объявленный на уровне модуля может иметь не более 16,128 элементов. Общий объем скалярных данных на уровне модуля ограничен 64К байтами, а каждый элемент типа Long занимает 4 байта. 2.10.4. Ограничения на файловые операции и операции ввода/вывода Maximum Item Максимальное число одновременно открытых файлов ... Определяется конкретным продуктом, использующим LotusScript Максимальный номер для оператора Open 255 Максимальное значение recLen в операторе Open 32767 Максимальная длина строки, которая может быть записана операторов Write 255 символов Максимальное число элементов в операторах Print, Write, Input 255 Максимальное число символов в пути в операторах MkDir, RmDir, ChDir 128 включая символ, задающий имя устройства 2.10.5. Ограничения компилятора и структуры скрипта Элементы языка: Элемент Максимальное число Число символов в идентификаторе LotusScript, не считая суффикс типа данных 40 Число аргументов процедуры или функции 31 Число меток в операторе On...GoTo 255 Показатель Notes версий 4.x Максимальное . число строк скрипта или включаемого файла (без учета файлов, подключаемых директивой %lnclude) Notes версий 5.x 64К 64К файлов, 16 16 Число ошибок компиляции до прекращения компиляции скрипта 20 20 Различно 64К Глубина вложений подключаемых директивой %Inciude Число символов в таблице 1 InterTrust Co. Тел (095) 9567928 344 Язык LotusScript символов на уровне модуля Число рекурсивных вызовов (уровень рекурсии) функции Ограничено 32К байтным стеком Ограничено 32К байтным стеком Объем данных в указанной области видимости Модуль: 64К bytes Модуль: Ограничено только доступной памятью Класс: 64К bytes Процедура: 32К bytes Размер исполняемого кода модуля 64К байт Класс: 64К bytes Процедура: 32 К. bytes Ограничено только доступной памятью Как видно из таблицы, ограничение на. размер стека времени исполнения остается; возможно, оно будет снято в будущих версиях. Снятие ограничения 64kb на размер исполняемого кода модуля значительно увеличивает возможности разработчика создавать крупные модули на LotusScript, Раньше разработчики были вынуждены разбивать модули на несколько библиотек скриптов. Данное усовершенствование позволяет значительно повысить стройность приложений. Ограничения на объем данных в указанных областях видимости распространяется только на переменные со значениями фиксированного размера: переменные скалярных типов данных исключая строки переменной длины; типы, определенные пользователем; фиксированные массивы скалярных типов данных. Изменение порядка объявления переменных может за счет изменения внутреннего выравнивания данных обеспечить некоторый дополнительный выигрыш по емкости. Например, переменные типа Integer имеют 2-х байтное выравнивание, а переменные типа Long - 4-х байтное. Максимальный объем данных «динамических» переменных (строки переменной длины, списки, динамические массивы, экземпляры классов) ограничен только объемом доступной памяти. В то же время каждая такая переменная занимает 4 байта в своей области видимости. По внутренним причинам LotusScript может формировать ошибку «Out of stack» непосредственно перед достижением предела емкости. 2.11. Отличия использования LotusScript на различных платформах В силу наличия особенностей, присущих каждой операционной системе - платформе, использование некоторых элементов языка LotusScript в скрипте так, как было описано выше, может привести к совершенно неожиданному для пользователя результату, а в ряде случаев использование некоторых элементов языка может вообще оказаться невозможным. Далее, в виде сводных таблиц и пояснений, представлены особенности и отличия функционирования этих элементов LotusScript версии 4 на наиболее широко распространенных операционных платформах. Левая графа такой таблицы содержит имя элемента LotusScript, правая графа содержит краткое описание отличий и особенностей применения данного элемента в используемой платформе. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (@-фармулы, LotusScript, встроенные классы LotusScript и Java 345 2.11.1. OS/2 Отличия и особенности использования элементов языка Реакция системы на использование элемента в скрипте Элемент языка Command Аргументы командной строки не могут нормально использоваться в OS/2. Однако, если используемый продукт Lotus разрешает использование таких аргументов, их значения передаются в скрипт при использовании функции Command, хотя, возможно, и не всегда верно. CreateObject Не поддерживается. Вырабатывается ошибка периода выполнения. GetObject Не поддерживается. Вырабатывается ошибка периода выполнения. Shell Режим активации окна не поддерживается в OS/2 ни для системных приложений, ни для приложений пользователя, использующих для хранения элементы среды Profile. Отличия файловой системы LotusScript поддерживает файловые системы HPFS и FAT. Файловая система HPFS допускает использование так называемых "длинных" имен файлов, количество символов в которых может достигать 254. Для имен файлов можно использовать любой регистр клавиатуры. Использование в скриптах длинных имен файлов вызовет ошибку в файловой системе FAT. 2.11.2. UNIX Отличия и особенности использования элементов языка Элемент языка Реакция системы на использование элемента в скрипте ActivateApp Не поддерживается. Вырабатывается ошибка периода выполнения. ChDir Вырабатывается ошибка периода выполнения, если LotusScript не может интерпретировать аргумент ChDir. например, если в аргументе содержится буква определяющая устройство. ChDrive CurDir, CurDir$ Вырабатывает ошибку периода выполнения, если спецификация устройства по умолчанию не равна пустой строке (""). CreateObject Не поддерживается. Вырабатывается ошибка периода выполнения. CurDrive, Возвращают пустую строку (""), т.к. в UNIX нет буквенных CurDrive$ обозначений устройств. . В UNIX секретность и целостность данных обеспечивается тем, что только супервизор может изменять данные. Любая другая попытка изменения данных (в данном случае системной даты и/или времени) вызовет ошибку периода выполнения скрипта. Date, Date$ Time, T'ime$ Declare Не поддерживаются соглашения языка Pascal для вызова внешних функций. Все внешние функции вызываются с использованием CDECL соглашения о вызовах. Не поддерживается спецификация числа с © InterTrust Со. Тел. (095) 9567928 Язык LotusScript 346 использованием предложения Alias. Dir, Dir$. Игнорируется опция attributeMask. Эти функции ведут себя так, как если бы атрибут у всех файлов был Normal. FileLen, Len, LenB, LenBP, LOF В конце строки содержится такой же символ окончания строки, как и в платформе DOS/Windows. Поэтому, значения, возвращаемые этими функциями, могут незначительно отличаться в платформах UNIX и Windows. GetFileAttr Вырабатывается ошибка периода выполнения, если буква, обозначающая устройство включена в аргумент. Следующие атрибуты файлов не возвращаются: ATTR HIDDEN, ATTR ARCHIVE, ATTR VOLUME ATTR_SYSTEM. GetObject При попытке использования вырабатывается ошибка периода выполнения. Input #, Input, lnput$, InputB, InputBS, Line Input, Print, Write # Составляются с использованием особенностей используемой платформы, в частности - назначений символов в UNIX, используемого символа окончания строки, порядка следования байтов и точности вычислений с помощью функций LotusScript. IsObject, IslJnknown См. ниже "Другие отличия". Open, Lock, Unlock Явное и неявное обеспечение секретности доступа к файлу не поддерживается в UNIX. LotusScript для UNIX допускает использование операций копирования, открытия, и т.д., файлов уже открытых для чтения. Оператор Open используется только для файлов статус доступа к которым определен как Shared. Использование Lock, Unlock, Lock Read, Lock Write и Lock ReadWrite вызывает ошибку периода выполнения. SendKeys Не поддерживается. Вырабатывается ошибка периода выполнения. SetFileAttr Игнорируются следующие атрибуты файла: ATTR HIDDEN, ATTR_ARCH1VE, ATTR_VOLUME. Shell Игнорируется режим окна. Отличия файловой системы LotusScript поддерживает все аспекты обеспечения секретности в UNIX. Отличается использование операторов Kill, Open, и RmDir, т.к. в платформе UNIX не используются буквенные обозначения устройств, используемые в этих операторах. При использовании пути к файлу, содержащего буквенное обозначение устройства, возвращается ошибка. Использование директивы %lnclude порождает ошибку компиляции, для остальных случаев выдается ошибка периода выполнения. (Заметим, что в UNIX допускается использование символа двоеточие ( : ) в имени файла, поэтому, использование оператора Dir$("a:") является законным. Просто, в этом случае в текущем каталоге ищется файл с именем а: ). UNIX использует символ "/" в качестве разделителя каталогов, в отличие от платформ DOS/Windows, использующих символ "V. LotusScript поддерживает использование обоих символов со следующими ограничениями: © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 347 * буквенная строка: если символ "/" используется в буквенной строке, являющейся путем к данным, файл .LSO порождается только в платформах, поддерживающих использование этого символа, например, в платформе UNIX. * строковые переменные: если переменной присваивается значение символьной строки, содержащей символ "/" и значение этой переменной является указателем пути к файлу, то, при передаче значения этой переменной операционной системе, будет порождаться ошибка периода выполнения, если используемая платформа не поддерживает использование символа "/" в указателе пути. UNIX допускает более широкое использование символов в указателях пути к данным. Так, например, в UNIX можно использовать более одной точки в указателе пути. LotusScript не поддерживает использование таких имен. UNIX использует в качестве символа "перевод строки" символ ASCII 10. Другие платформы могут для этой цели использовать другие символы. Это может привести к отличиям в размерах одних и тех же файлов в разных платформах, а также к неверной трактовке содержащейся в них информации. Другие отличия Использование спецификатора Alias с номером С-функции в операторе Declare, невозможно в UNIX, т.к. UNIX не использует нумерацию экспортируемых библиотекой функций. Функцию IsObject можно использовать, если используется ссылка на объект из данной процедуры или на объект продукта, но не на объект OLE, т.к. объекты OLE не существуют в платформе UNIX. Функция IsUnknown в платформе UNIX всегда возвращает значение False, т.к. в UNIX нет средств передачи значения VJUNKNOWN в выражение типа Variant. 2.11.3. Macintosh Отличия и особенности использования элементов языка Элемент языка Реакция системы на использование элемента в скрипте ActivateApp Не поддерживается. Вырабатывается ошибка периода выполнения. ChDir Поддерживается, как средство смены устройства, т.к. в Macintosh спецификация устройства имеет вид: "Hard drive:folderl : folder2:". ChDrive Вырабатывается ошибка периода выполнения, если аргумент не содержит пустую строку (""), определяющую устройство по умолчанию. Для смены устройства используется оператор ChDir. Command Командная строка аргументов не может нормально использоваться в Macintosh Однако, если используемый продукт Lotus разрешает использование таких аргументов, их значения, при использовании функции Command, все таки передаются в скрипт. CurDir Вырабатывается ошибка периода выполнения, если аргумент, определяющий устройство по умолчанию или в явном виде не содержит пустую строку (""). Declare Не поддерживаются соглашения языка Pascal для вызова функции из библиотек DLL. © InterTrust Co. Тел. (095) 9567928 348 Язык LotusScript Dir Игнорирует атрибуты файлов Hidden Files, Volume Label и System. He возвращает в спецификации каталогов символы "," и "..". Environ Возвращает пустую строку. Вырабатывает ошибку периода выполнения только при передаче недопустимого значения аргумента, например, недопустимого числового значения. FileLen Символ, ограничивающий строку в файле, отличается от используемого в DOS. Длина файла может оказаться неверной. GetFileAttr Следующие атрибуты фалов не возвращаются: ATTR ARCFUVE, ATTR_VOLUME, ATTR_SYSTEM. ten, LenB Строка, прочитанная из файла, содержит ограничитель строки, отличающийся от такого символа в платформе DOS. Возможно неверное определение длины строки. SendKeys Fie поддерживается. Вырабатывается ошибка периода выполнения. SetFileAttr Вырабатывается ошибка, если передается атрибуту ATTR ARCHIVE или A1TRJSYSTEM. Shell He поддерживается. Вырабатывается ошибка периода выполнения. Отличия файловой системы Платформа Macintosh не использует для указания пути знак "\". Этот символ используется для определения пути в платформе DOS. Имена файлов не ограничиваются, как в DOS, 8-и символьными именами и 3-х символьными расширениями. Macintosh не хранит назначение каталога по умолчанию для каждого устройства. Он поддерживает только текущий каталог. Имя устройства может иметь длину 27 символов. Это огранич ивает действие операторов ChDir, ChDrive, и CurDir. Macintosh не поддерживает в спецификации каталогов символы "." и "..". что ограничивает использование функции Dir. В файловой системе Macintosh не поддерживается использование атрибутов файлов Hidden, Volume, Archive, и System. Это ограничивает возможности использования операторов Dir, GetFileAttr и SetFileAttr. Macintosh использует символ "возврат каретки" (ASCII 13) в качестве символа конца, строки. . . - •. Эти отличия вынуждают LotusScript использовать при выполнении различные наборы кодов, с учетом того, что даже одинаковые файлы в разных платформах могут иметь разные размеры. Например, с учетом правил кодирования, в UNIX и в Macintosh размеры одних и тех же файлов эквивалентны. Эти же файлы на платформе Windows будут иметь больший размер, т.к. в Windows используется 2-х байтовая схема кодирования символов. Эти отличия ограничивают эффективность использования функций FileLen, Len, LenB, и LenBP. Maci nt osh допускав! выполнение ряда операций с уже открытыми файлами С копирование, откпытие и т. л Л. что ограничивает использование Onen. Lock, и Unlock. О InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 349 3. Встроенные классы для создания приложений Domino Встроенные классы предназначены для разработки приложений Domino на LotusScript и Java. Используя объекты этих классов, разработчик приложений получает из LotusScript или Java доступ к базам данных Domino и содержащимся в них объектам (видам, документам, полям в документе...), а из LotusScript так же и к объектам интерфейса пользователя. В поставку Domino/Notes версии 5.0 входит 31 «почти общий» для LotusScript и Java встроенный класс, еще 7 классов, доступных только в LotusScript, и несколько специфических классов, присущих только Java. В версии 5.0 было добавлено 8 «совершенно новых» встроенных классов. Если задаться целью проследить «общие» свойства и методы классов для LotusScript и Java, то обнаружится, что их более 85%. В совокупности все встроенные классы, без двойного подсчета «общих» для LotusScript и Java, имеют в настоящее время около 800 свойств и методов. Мотивы, по которым в данной главе было решено «проводить параллель» между свойствами и методами встроенных классов LotusScript и Java, следующие. • Многие разработчики приложений Notes, знакомые с LotusScript по версиям Notes 4.x, еще не в полной мере владеют Java применительно к Domino, и такое сопоставление для них окажется полезным. • Хотя полного пересечения между методами и свойствами встроенных классов LotusScript и Java нет, оно имеется ориентировочно на 85%, так что «параллельность» изложения позволяет существенно сократить объем и степень дублирования излагаемого (и изучаемого) материала. • «В разных местах» приложений Domino приходится использовать «коктейль» из нескольких разных языков: @-формулы, JavaScript, LotusScript и Java, и совсем не удается обойтись только одним из языков. В данной главе была использована следующая система обозначений и сокращений. • • • • Конструкция [Notes]<Hci3eanue класса>, например, [NotesJDatabase, означает, что в LotusScript класс называется NotesDatabase, а в Java - Database. Конструкция <значение в LotusScript/<значение в Java>, например, ""/null, означает, что в LotusScript это значение равно "", а в Java - null. В описаниях синтаксиса свойств и методов Java в отличие от «классического стиля» опущены public и throws Notes Exception (поскольку все свойства и методы имеют «тип видимости» public и почти все свойства и методы могут возбуждать исключения) и добавлены имя переменной, содержащей возвращаемое значение, знак равенства и название класса, к которому применяется метод (чтобы «подчеркнуть подобие» синтаксису в LotusScript). Так, вместо классического public Java.Mil. Vector getAddressBooksQ throws NotesException дается java.util Vector database Vector = Se^sTOn.getAddressBooksQ В примерах на языке LotusScript обычно опускаются «заголовки» процедур. Так, для следующего скрипта кнопки «останется» только то, что выделено жирным шрифтом. Sub Click(Source As Button) Dim db As New NotesDatabase( "", "names.nsf" ) Dim parentDb As NotesDatabase Dim acl As NotesACL Set acl = db.ACL Set parentDb = acl.Parent Messagebox( db.Title ) Messagebox( parentDb.Title ) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 350 End Sub • Большинство примеров приложений на Java относится к агентам. Поскольку при создании нового агента в интерфейсе Domino Designer версий 5 автоматически генерируется «шаблон для его тела», в примерах приводится только то, что было действительно добавлено вместо строки // (Your code goes here) в генерируемый при создании агента шаблон, а так же «дополнительно добавленные» операторы import. При этом переменные session и agentContext в примерах всегда нужно трактовать так, как это определено в шаблоне. Например, для следующего скрипта агента «в примере остается» только то, что выделено жирным шрифтом. import lotus. domino .*; . import Java.util.*; • -: . ' " public class JavaAgent extends AgentBase { . ' • • public void NotesMain() • { try { Session session = getSession(}; AgentContext agentContext = session.getAgentContext(); // (Your code qoes here) Database db; Vector books = session.getAddressBooks(); Enumeration & = books.elements(); while (e.hasMoreElements()) -.-.-.-.{ db = (Database)e.nextElement(); String fn = db.getFileName(); к , ' •• String server; ' "J if (db.getServer(} != null) server = db.getServer() else server - "Local"; if (fn != null) db.open(); String title = db.getTitle(); System.out.println (server + " " + fn + " \"" + title + »\»") ; ....} , } catch(Exception e) { e .print St. ackT race (); • } } - . : • } . • * . ' . ' - , Имена методов всюду приведены с «малой буквы», а свойств - с «большой буквы». По крайней мере по этому признаку можно отличить методы от свойств в предметном указателе. Свойства и методы, добавленные или модифицированные в Dornino версии 5.0, «отмечены в заголовках значком» ©. ©InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @~формулы, LotusScript, встроенные классы LotusScript и Java 351 3.1. Введение в встроенные классы Domino • • Встроенные классы Domino можно разделить на две группы: классы интерфейса пользователя (User Interface, UI) или классы «переднего плана». классы «заднего плана» (back-end). Классы интерфейса пользователя доступны только из LotusScript и позволяют разработчику приложений эмулировать многие действия, возможные в интерфейсе пользователя Notes. Они обеспечивают доступ к таким объектам пользовательского интерфейса, как рабочее пространство Notes (Workspace), окно вида (View window), окно документа (Document window), поле, поле произвольного текста (RichText), кнопка в окне документа... Действия, выполняемые над объектами классов интерфейса пользователя, отображаются в пользовательском интерфейсе, т.е. «происходят» как бы «на сцене, на переднем плане». Класс NotesUIWorkSpacc представляет- интерфейс пользователя Notes (рабочее пространство) и обеспечивает доступ к содержащемся в нем объектам. Класс NotesUIDatabase представляет базу данных в интерфейсе пользователя, класс NotesUIView • вид в интерфейсе пользователя, класс NotesUlDocument - документ, который в текущий момент выбран или открыт в интерфейсе пользователя, класс NotesTimer - «таймер» механизм для получения событий через установленный интервал времени, класс Field редактируемое поле в форме, по которой открыт документ, класс Button - акцию, кнопку или «активную площадку» (hotspot) в форме или поле типа RichText, а класс Navigator - кнопку, «активную площадку» или другой объект в навигаторе, открытом в интерфейсе пользователя. Классы «заднего плана» (back-end) доступны как в LotusScript, так и в Java, и представляют такие объекты Domino, как базу данных, вид или папку, агента, документ, поле в документе... Программисте использованием объектов этих классов может манипулировать перечисленными объектами Domino из разработанных им приложений. При этом выполняемые над объектами действия происходят без явного отображения в пользовательском интерфейсе, как бы «за сценой, на заднем плане». Класс [Notes]Session является «корневым» в «контейнерной» иерархии встроенных классов Domino. Объект класса [NotesJSession представляет текущую сессию (сеанс). Он обеспечивает доступ к переменным среды, адресным книгам, текущей базе данных и текущему агенту, позволяет получать информацию о текущем пользователе, текущей платформе и номере реализации Notes, используется для «отметки» обработанных агентом документов и обеспечивает возможность создания объектов некоторых других классов без явного создания объектов, являющихся контейнерами для создаваемых. Класс AgentContext присутствует только в составе встроенных классов Java и инкапсулирует те свойства и методы, которые присущи только выполняющемуся агенту и не имеют смысла в иных контекстах. Класс [NotesJDbDirectory представляет все базы, расположенные на указанном сервере или локальном компьютере. Позволяет программисту «просмотреть» список имеющихся баз и получить доступ к любой из них. Класс [NotesJDatabase представляет конкретную базу Domino и обеспечивает доступ ко всем содержащимся в ней объектам. Класс j'N'otesjRepIication позволяют определять и устанавливать ряд свойств базы данных, касающихся ее поведения при репликациях. Класс [Notes]ACL представляет список управления доступом (ACL) базы. Одной из составляющих частей ACL является набор элементов (ACL Entry), каждый из которых описывает права доступа к базе конкретного пользователя, сервера или группы. Класс [NotesjACLEntry представляет один элемент из набора элементов в ACL. © InterTrust Co. Тел. (095) 9567928 352 Встроенные классы LotusScript и Java Класс [NotesjOutline представляет новый элемент дизайна Domino версий 5 -«иерархическую навигационную схему». Навигационная схема в свою очередь состоит из набора иерархически («древовидно») упорядоченных элементов, выбор которых пользователем влечет выполнение некоторого действия или переход по ссылке. Для работы с элементом схемы используется объект класса [NotesJOutlineEntry. Класс [NotesjAgent представляет конкретного агента, а класс [Notes]Form - конкретную форму в базе. Класс [NotesjDocumentColIection представляет коллекцию (подмножество) документов из базы, отобранную в соответствии с некоторым критерием, Класс [NotesJView представляет вид или папку в базе и обеспечивает доступ содержащимся в виде или папке «строкам вида» и документам. Класс [Notes]ViewColumn представляет столбец вида или папки. Класс [Notes]ViewEntryCoIlection представляет коллекцию из всех строк вида или только некоторое подмножество строк вида. Порядок следования элементов в такой коллекции совпадает с порядком следования соответствующих строк в «родительском» виде. Каждый элемент из коллекции - «строка вида» - является объектом класса [NotesjViewEntry. Класс [Notes] ViewNavigator предоставляет более продвинутые возможности для навигации на программном уровне по виду или части вида. Класс [Notes]Document представляет один документ в базе. Класс [Notes]Item представляет одно поле из документа - часть данных из документа, которая обычно отображается в интерфейсе пользователя в одном поле формы. Когда документ создается по некоторой форме, информация, введенная пользователем или вычисленная, для каждого из полей формы (кроме вычисляемых для показа), сохраняется в документе и образует одно поле этого документа. Однако, используя LotusScript или .lava, программист имеет возможность создавать документы и работать с существующими документами, никак не привязываясь при этом к конкретной форме для показа этих документов. Поэтому поле в форме (Field) и поле в документе (Item) - это совершенно разные объекты, хотя часто и связанные между собой. Класс [Notes]RichTextItem представляет в документе одно поле типа «произвольный текст» (RichText). Этот класс является производным от класса [Notesjltem, т.е. он наследует все свойства и методы базового класса, но дополнительно имеет и свои собственные специфические свойства и методы для работы с произвольным текстом. Класс [Notes]RichTextStyle служит для определения стиля текста в поле типа RichText, а классы [Notes]RichTextParagraphStyle и [Notes]RichTextTab - стиля абзаца и положений табуляционных меток в абзаце поля типа RichText. Класс [NotesjEmbeddedObect представляет внедренный объект, связанный объект или присоединенный файл, содержащийся в объекте класса [Notes]RichTextltem, а с точки зрения пользователя - в поле типа RichText. Класс [NotesJLog позволяет протоколировать выполняемые при работе приложения действия и возникающие при этом ошибки. Результат протоколирования может быть помещен в базу, почтовое сообщение, файл (если выполнение происходит локально) или в протокол агента. Класс [Notes]NewsLetter позволяет создавать документы, содержащие информацию из других документов, или документы, содержащие ссылки (DocLink-и) на многие другие документы. Класс jNotesJRegistration применяется при создании и администрировании ID-файлов и «связанных» с ними документов в адресной книге сервера (с версии 5.0 она называется Domino Directory). Методы класса позволяют выпускать взаимные сертификаты, © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 353 ресертифицировать существующие ID-файлы, регистрировать новых пользователей, сертификаторов и серверы, включая создание ID-файлов, соответствующих документов в адресной книге сервера, и, для пользователей, создание почтовых баз. Класс также содержит методы, позволяющие извлекать или удалять присоединенные ID-файлы из документов в адресной книге сервера, «переключаться» на другой ID-файл, получать или изменять информацию в документах адресной книги сервера. Класс [Notes]DateTime служит для преобразования значений типа «дата-время» между форматами LotusScript/Java и Domino, а класс [NotesjDateRange представляет «отрезок времени». "> Класс [NotesjName предназначен для работы с именами или адресами пользователей или серверов. Класс [Notesjlnternational позволяет получить доступ к характеристикам среды (платформы), в (на) которой происходит выполнение приложения. Классы интерфейса пользователя Классы «заднего плана» (back-end) На Рис. 3.1 дается так называемая «контейнерная иерархия» встроенных классов. При этом объекты классов, находящихся на более высоких уровнях дерева, являются контейнерами для объектов, расположенных на более низких уровнях дерева. Речь идет вовсе не о наследовании классов. Каждый класс содержит члены (members): свойства (properties) и методы (methods). Отношение «является контейнером» (содержит) подразумевает, что находящийся «выше по дереву» класс имеет свойства и методы для © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript u Java 354 создания новых объектов или доступа к существующим объектам находящихся «ниже по дереву» классов. Следует только отметить, что приведенное на рисунке дерево не является совершенно «полным». «Полное» дерево выглядит сложнее и запутаннее, поэтому мы не приводим его целиком, но в описании каждого класса даем полную таблицу-поддерево «в окрестностях» рассматриваемого класса. «Контейнерная иерархия» находит свое прямое отражение при создании и использовании объектов. Рассмотрим следующий скрипт. 1. 2. 3. 4. 5. 6. 7. 8. 9. Dim Dim Dim Dim Dim Set Set Set Set session As New NotesSession db As NotesDatabase view As NotesView doc As NotesDocument item As Notesltem db = session.CurrentDatabase view = db.GetView("Main View") doc = view.GetFirstDocument item - doc.GetFirstItern .. - • 1. Переменная session объявлена как переменная типа NotesSession. Метод New создает новый объект класса NotesSession и присваивает переменной session ссылку на него. Этот объект представляет текущий сеанс пользователя. 2,3,4,5. Переменные db, view, doc и item объявлены соответственно как переменные классов NotesDatabase, NotesView, NotesDocument и Notesltem. Этим переменным пока не присвоены значения - они пока не связаны ни с какими объектами. 6. Переменной db присваивается ссылка на объект1 класса NotesDatabase, возвращаемая свойством CurrentDatabase объекта session. Этот объект «содержится» в объекте класса NotesSession, он представляет текущую базу в сеансе пользователя. 7. Переменной view присваивается ссылка на объект класса NotesView. возвращаемая методом getView объекта db. У объекта db - базы данных - может быть несколько видов, и метод getView имеет параметр - строку с названием вида. Здесь метод getView создает и возвращает ссылку на объект, представляющий вид с названием "Main View". 8. Переменной doc присваивается ссылка представляющий первый документ в виде view. па объект класса NotesDocument, 9. Переменной item класса Notesltem присваивается ссылка на объект класса Notesltem, представляющий первое поле в документе doc. Из рассмотренного примера становится очевидной следующая «контейнерная иерархия» классов: NotesSession —> NotesDatabase -> NotesView —> NotesDocument —» Notesltem. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @гформулы, LotusScript, встроенные классы LotusScript и Java 355 3.2. Основы разработки Java-приложений, использующих ; встроенные классы Domino Пакет lotus.domino В любом Java-приложении, использующем классы Domino (программе, апплете, агенте или сервлете), должен быть «импортирован» пакет lotus.domino. Для обеспечения совместимости с Domino версии 4.6 пакет lotus.domino содержит те же классы и методы, что и «старый» пакет lotus.notes, а так же новые классы, методы и другие расширения. Пакет lotus.domino допускает как «локальные», так и «удаленные» (ПОР) вызовы к объектам Domino. * Локальные вызовы (local calls) используют исполняемый код с локального компьютера, поэтому на локальном компьютере должен быть установлен Domino. Подробнее это означает следующее. Когда вы «вызываете» в своем Java-приложении какой-либо метод встроенного класса, например, Database db = DbDir.openDatabase("myDbFile.nsf"), то для объекта DbDir происходит вызов метода openDatabase класса DbDirectory. Байт-код метода openDatabase находится в пакете lotus.domino. Однако в самом байт-коде метода для выполнения необходимой операции производится т.н. native-вызов С-функции из библиотеки динамической компоновки, входящей в состав установленного на локальном компьютере Domino. Эта С-функция или «полностью самостоятельно» реализует «запрошенную» вами операцию, или, если это необходимо, обращается к серверу Domino, используя при этом Notes RFC (Remote Procedure Call). Рис. 3.2 Общая схема «локальных» вызовов • Удаленные (ПОР) вызовы (remote calls) используют исполняемый код с сервера Domino, так что в этом случае на локальной машине нет необходимости устанавливать Domino. DommoHCORBA-.••.•..•••;,••••:•••::.•• • . . . :. : .-. •..•,-•..,.••,..; • .. . . .....-.••• ..... CORBA (Common Object Request Broker Architecture) - архитектура брокера запросов объектов - спецификация, принадлежащая некоммерческой группе Object Management Group (OMG). OMG - консорциум промышленных корпораций, членами которой являются Lotus, IBM, Netscape и более 700 других компаний, имеет Web-сайт http://www.omg.org. CORBA специфицирует базовые механизмы для вызова с компьютера клиента методов объектов, которые находятся на компьютере сервера. ORB (Object Request Broker) - брокер запросов к объектам. Это распределенное приложение, функцией которого является © InterTrust Co. Тел. (095) 9567928 356 Встроенные классы LotusScript и Java предоставление механизма выполнения запроса, сделанного клиентом, на вызов метода объекта, находящегося на сервере. Для связи между брокером запросов клиента и брокером запросов сервера (а более широко, между разными брокерами запросов), разработан протокол GIOP (General Inter-ORB Protocol), стандартизующий множество форматов сообщений и низкоуровневое представление передаваемых данных. Реализация GIOP «поверх» протокола TCP/IP - ПОР (Internet Inter-ORB Protocol) - протокол связи между двумя компьютерами, обеспечивающий передачу параметров для вызываемого метода, его вызов и возврат значения метода клиенту. .. ; , Программное обеспечение брокеров запросов клиента и сервера могут быть написаны на разных языках программирования и разными производителями, но, являясь CORBA-совместимыми, «общаются» между собой по протоколу ПОР. Чтобы было возможным формально описывать методы объектов независимо от языка программирования, на котором эти объекты действительно реализованы, в CORBA предусмотрен IDL (Interface Definition Language) - язык определения интерфейсов. Описание объекта (класса) на IDL содержит лишь имена методов и их сигнатуры (имена и типы параметров, типы возвращаемых значений), но никак не затрагивает вопросов реализации методов. Имеются трансляторы с языка IDL на разные языки программирования для различных платформ. Результат работы таких трансляторов дает две компоненты: «скелетную» реализацию классов для «стороны» сервера (skeletons, «скелетоны») и «полную» реализацию этих классов для «стороны» клиента (stubs, «стабы»). Разработчик объектов (в нашем случае Lotus) должен обеспечить «реальный» код для сервера, «дополняя» код «скелетонов», сгенерированный IDL-транслятором. Для «клиентской стороны» ничего разрабатывать не нужно, за исключением, разумеется, самого приложения или апплета, осуществляющего вызовы необходимых клиенту методов. Байт-код «стабов» и клиентского брокера запросов обычно загружаются в броузер клиента «как JAR-файл». «Стабы» сами формируют пакеты из входных параметров для каждого вызываемого клиентом метода в ПОР-совместимом буфере и посылают эти пакеты через клиентский брокер запросов брокеру запросов сервера. Затем «стабы» ожидают заполнения буфера ответов сервером и, если метод определен с возвращаемым значением, распаковывают это значение из буфера и возвращает его. Рис. 3.3 Обгцая схема «удаленных» вызовов объектов Domino © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (ф-формуды, LotusScript, встроенные классы LotusScript и Java 357 Требования к серверу Удаленные (ПОР) вызовы требуют установки «на серверной стороне» сервера Domino только версий 5.x. На сервере должны быть запущены задачи HTTP (она так же известна как Domino Web Server) и DJIOP (Domino Internet Inter-Object request broker Protocol). В документе Server применительно к задаче ОПОР обратите внимание на заполнение следующих полей. , • Internet Protocols - ПОР - в поле Number of threads задается количество подпроцессов задачи ОПОР для обработки удаленных вызовов. SERVER' N<rtesSrv40b/lnterTnntOorp/Sl! Puc. 3.4 Количество подпроцессов задачи DIIOP Ports - Internet Ports - HOP - номера портов (TCP/IP port number), статус портов (TCP/IP port status), анонимный доступ и разрешенные способы аутентификации (Authentication options) для доступа к DIIOP по «обычному» порту TCP/IP и порту TCP/IP с поддержкой SSL. SERVER: NotesSrv400/tn,torTrustCorp/ SLJ Basics Security Ports Server Tasks Internet Protocol: j Mi/'w I Miici ) Notes Network Ports Internet Ports Proxies SSL key We name: " keyfile.kyrj SSL protocol version (for use with all protocols except HTTP): Accept SSL site certificates: r*Negotiated_i_»j О Yes <?< No Accept expired SSL Щ' Yes О No certificates: Web j Directory ] News ] Mail j HOP ] TCP/IP port number: : TCP/IP port status: Authentication options: Name & password: Anonymous: SSL port number: SSL port status: Authentication options: Client certificate: Name & password: Anonymous: 63148 ± Enabled _»j Yes ^j ' Ye s j j 63149* 'Enabled jj N/A '"Yes _,-jJ ' Yes -,^ Puc. 3.5 Используемые порты и способы аутентификации для задачи DIIOP 1 * 1 InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 358 Security - Server Access - поля Access server. Not access server. Create new databases и Create replica databases содержат списки имен, шаблонов имен и групп, кому разрешается или не разрешается обращаться к серверу Domino, создавать на нем новые базы или реплики баз. Если кто-то не имеет доступа к серверу, или имеет, но, например, не может создавать на нем новые базы, то он не сможет этого сделать ни из клиента Domino, ни «через задачу» DIIOP. Security - ПОР Restrictions - в этой группе два поля, содержащие списки имен, шаблонов имен или групп тех, кому разрешается выполнять «удаленные» приложения на Java или Javascript с «ограниченными» или «неограниченными» функциональными возможностями. В ходе процесса аутентификации, происходящего при получении удаленным приложением объекта Session, задача DIIOP проверяет вхождение имени клиента в списки из этих полей. Чтобы к задаче DIIOP был возможен и анонимный доступ, необходимо поместить имя "Anonymous" в одно или оба поля. SERVER Notes8rv40GiJn1er1iutitCofplS. Basics I Security Ports Smf-i li: 1 -- | Internet Pn > Puc. 3.6 Поля, определяющие возможность доступа к задаче DIIOP Задача DIIOP автоматически обновляет информацию из документа Server, касающуюся доступа, в своем кэше приблизительно раз в полчаса. Команда консоли сервера Tell DIIOP Refresh «обязывает» задачу DIIOP осуществить внеплановое обновление информации в кэше. Требования к компьютеру, на котором выполняется разработка приложений Компиляция Java-приложений, использующих классы Domino, должна выполняться на компьютере с установленным Domino Designer версий 5.x. Убедитесь, что в файле NOTES.INI этого компьютера имеется строка ALLOW NOTES PACKAGE APPLETS=1 © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (tv-формулы, LotusScript, встроенные классы LotusScript и Java 359 Кроме того, переменная окружения CLASSPATH должна содержать путь на JAR-файлы пакета lotus.domino: set CLASSPATH=<other>;c:\notes\domino\java\NCSO.jar;с\notes\Notes.jar Архив Notes.jar содержит «высокоуровневый» пакет lotus.domino, пакет lotus.domino.local для локальных вызовов и «старый» пакет lotus.notes. Архив NCSO.jar (NCSO - Notes Client Side Objects - объекты Notes для «стороны» клиента) содержит «высокоуровневый» пакет lotus.domino и пакет lotus.domino.corba для удаленных вызовов. Строго говоря, если вы компилируете только удаленные вызовы, то необходим только NCSO.jar. а если вы компилируете только локальные или «старые» обращения, необходим только Notes.jar. Код вашего класса должен «импортировать» пакет lotus.domino import lotus.domino.*; Требования к компьютеру, на котором выполняется Java-приложение На компьютере, выполняющем Java-приложение, осуществляющее «локальные» вызовы свойств и методов классов Domino, должен быть установлен Domino версий 5.x (Client, Designer или Server), а переменная окружения CLASSPATH должна содержать путь к архиву Notes.jar. Кроме того, в переменную окружения PATH необходимо добавить каталог программ Domino (например, c:\notes), чтобы виртуальная машина Java могла находить и загружать библиотеки динамической компоновки, которые необходимы Java-классам. Естественно, необходим и ID-файл, поскольку доступ к серверу в этом случае осуществляется «по каналам Notes» (т.е. посредством Notes RFC) под текущим (указанным в файле NOTES.IN! в переменной KeyFilenarne) ID-файлом. На компьютере, выполняющем Java-приложение, осуществляющее «удаленные» вызовы свойств и методов классов Domino, нет необходимости устанавливать Domino. Однако на этом компьютере должен присутствовать архив NCSO.jar, а переменная окружения CLASSPATH должна содержать путь к архиву NCSO.jar. Domino-агент, написанный на Java, может выполняться только на компьютере с установленным Domino версий 5.x (Client, Designer или Server), Переменная окружения CLASSPATH на этом компьютере должна содержать путь к архиву Notes.jar. На компьютере, выполняющем апплет, осуществляющий «удаленные» вызовы свойств и методов классов Domino, нет необходимости ни в программном обеспечении Domino, ни в каких-либо специальных назначениях в CLASSPATH. 3.2.1. Класс NotesThread Класс NotesThread «расширяет» класс Java.lang.Thread (является наследником). Класс был создан разработчиками Domino для того, чтобы обеспечить и гарантировать выполнение для каждого потока необходимого кода инициализации и завершения Domino. Если вам приходилось разрабатывать программы на языке С, использующие функции NotesAPI, вспомните, что в однопоточной программе перед вызовом функций NotesAPI вы должны были вызывать функцию NotesInitExtendedQ, основные действия которой сводились к нахождению каталога данных Notes, загрузке файла NOTES.INI и поиску ID-файла пользователя, а по завершении использования функций NotesAPI вызвать функцию NotesTermQ. В случае же многопоточной программы в каждом потоке (thread) перед вызовом функций NotesAPI требовалось вызывать функцию NotesInitThreadQ, а по завершении использования функций NotesAPI - функцию NotesTermThreadQ. Java-программы и сервлеты, выполняющие «локальные» вызовы свойств и методов классов Domino, должны явно использовать класс NotesThread. Напротив, Java-приложения, выполняющие «удаленные» вызовы, не должны использовать класс NotesThread. Java-приложения, которые выполняют как локальные, так и удаленные вызовы, «должны сами динамически определять», когда должны выполняться локальные вызовы, и в этом случае © InterTrust Со. Тел. (095) 9567928 360 Встроенные классы LotusScript и Java «пользоваться» статическими методами sinitThread и stermThread класса NotesThread. Потоки, активизированные AWT и использующие локальные вызовы к объектам Domino, «должны пользоваться» статическими методами sinitThread и stermThread класса NotesThread. Агенты «расширяют» класс AgentBase, который в свою очередь расширяет класс NotesThteacl. В агентах "применяются только локальные вызовы классов Domino, но при их разработке не требуется явное использование класса NotesThtead, поскольку все необходимые операции инициализации и завершения реализованы в самом классе AgentBase. Апплеты, выполняющие вызовы классов Domino, расширяют класс AppletBase, который «прозрачно для разработчика» выполняет локальные вызовы объектов Domino, если апплет выполняется в среде клиента Domino, и удаленные вызовы, если апплет выполняется в броузере. Для завершения работы Java-приложения, использующего класс NotesThread, никогда не должен применяться метод System.exit. Это относится и к агентам, расширяющим класс AgentBase, который в свою очередь является наследником класса NotesThread. Но если в агенте вызов System.exit генерирует исключение SecurityException, то в других Java-приложениях вызов System.exit может повлечь гораздо более серьезные проблемы. Спецификация класса NotesThread public class NotesThread extends Java.lang.Thread 1 // Конструкторы public NotesThread( ) ; public NotesThread(Runnable t ) ; public NotesThread(String name); public NotesThread(Runnable t, String name); public NotesThread(ThreadGroup group, String name); public NotesThread(ThreadGroup group, Runnable t, String name); public NotesThread(ThreadGroup group, Runnable t ) ; // Инициализация и завершение потока Domino public void initThread(); public void termThread(); // Статические: инициализация и завершение потока Domino public static void sinitThread ( ) ; • public static void stermThread!); // Метод run не может быть переопределен в производном классе public final void run(); // Метод run вызывает метод runNotes, // который вы обычно переопределяете в производном классе public void runNotes() throws NotesException; // Деструктор public void finalize!); •» public static void load(boolean debug) throws NotesException; Выполнение кодов инициализации и завершения Domino для потока путем наследования Класс Java-программы должен «явно расширять» класс NotesThread и содержать реализацию метода runNotes, в котором и осуществляются локальные обращения к классам Domino. Программа создает новый экземпляр своего класса и вызывает для него метод start. Поскольку в классе NotesThread метод start не переопределен, вызывается метод start класса © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 361 Java.lang.Thread. Он создает новый поток и «в нем» вызывает для объекта, метод run. Вы не можете переопределить метод run в своем классе, поскольку он объявлен в базовом классе NotesThread с модификатором final. Следовательно, всегда происходит вызов метода NotesThread.run, который сначала выполняет код инициализации Domino, а затем вызывает метод runNotes, который вы переопределили в своем классе. По завершении метода runNotes в методе NotesThread.run выполняется необходимый для Domino код завершения. Наконец, по завершении метода NotesThread.run выполнение потока завершается. Пример-шаблон I. Программа, обеспечивающая выполнение кодов инициализации и завершения Domino для потока путем наследования класса NotesThread, выполняет «локальный» вызов. import lotus.domino.*; public class Appl extends NotesThread { public static void main(String argv[]) { Appl t = new Appl(); t. start (}; } public void runNotes() { try { Session s - NotesFactory.createSession ( ) ; Storing p - s.getPlatform (); String u = s . get.UserName () ; System, out. println ("Local session for user ." + u + " on platform " + p); } catch (Exception e) { e.printStackTrace(); } ' } } -•.••-...• Результат выполнения этой программы может выглядеть следующим образом. D: \JavaEx\BookExamples \Templat es> Java Appl Local session for user CN=Nikolay N. Iontsev/0=InterTrustCorp/C=SU on platform Windows /32 Выполнение кодов инициализации и завершения Domino для потока реализацией интерфейса КшшаЫе Класс Java-программы должен реализовывать интерфейс Runnable и, как требует этот интерфейс, содержать реализацию метода run, в котором и осуществляются локальные обращения к объектам Domino. Применяется этот вариант обычно в тех случаях, когда ваш класс должен быть наследником другого класса (не NotesThread). Программа создает новый объект своего класса, затем новый объект класса NotesThread, передавая его конструктору в качестве параметра ссылку на объект своего класса. В конструкторе NotesThread происходит сохранение ссылки на объект вашего класса для использования в дальнейшем. Затем программа вызывает метод start для объекта NotesThread. Поскольку в классе NotesThread метод start не переопределен, вызывается метод start класса java.lang.Thread. Он создает новый поток и «в нем» вызывает для объекта NotesThread метод run, который сначала выполняет код инициализации Domino, а затем вызывает метод run (а не runNotes) вашего объекта, ссылку на который конструктор NotesThread «предусмотрительно сохранил» в объекте NotesThread. По завершении вашего метода run в методе NotesThread.run выполняется необходимый для Domino код завершения. Наконец, по завершении метода NotesThread.run выполнение потока завершается. ©InterTrust Со. Тел. (095) 9567928 Встроенные классы LotusScript u Java 362 Пример-шаблон 2. Программа, обеспечивающая выполнение кодов инициализации и завершения Domino для потока путем реализации интерфейса Runnable, выполняет «локальный» вызов. import lotus.domino. * ; public class App2 implements Runnable { public static void main(String argvf]) { App2 t = new App2(); NotesThread nt — new NotesThread((Runnable)t); rit. start (} ; } public void run() try { Session s = NotesFactory. creaf.eSession (); String p = s.getPlatform(); String u = s.getUserName(); System.out.println("Local session for user " + u + " on platform. " + p) ; } catch (Exception e) { e.printStackTrace (); } }} Результат выполнения этой программы может выглядеть следующим образом. D:\JavaEx\BookExamples\Templates>java Арр2 Local session for user CN=Nikolay N. Iontsev/O=InterTrustCorp/C=SU on p1 a t f orm Wi n dow s/3 2 Выполнение кодов инициализации и завершения Domino «явным» использованием статических методов Класс Java-программы перед выполнением локальных обращений к объектам Domino должен «явно» вызвать статический метод sinitThread, а по завершении обращений к объектам Domino «явно» вызвать статический метод stermThread (обычно в блоке finally). Пример-шаблон 3. Программа, обеспечивающая явный вызов «кодов» инициализации и завершения Domino для «основного» потока, выполняет «локальный» вызов. import lotus.domino.*; public class АррЗ { . . . public static void main(String argv[]) { try { NotesThread. sinitThread() ; •• Session s = NotesFactory.createSession(); String p = s.getPlatform(); String u = s.getUserName(); System, out. .println ("Local session for user " + u + " on platform " + p); ! . . , ' - • catch(Exception e) { e.printStackTrace(); } finally { NotesThread.stermlhread(); } } } Результат выполнения этой программы может выглядеть следующим образом. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: ^-формулы, LotusScript, встроенные классы LotusScript и Java 363 D:\JavaEx\BookExamples\Templates>java АррЗ • • Local session for user CN=Nikolay N. lontsev/O=InterTrustCorp/C=SU on platform Windows/32 3.2.2. Класс AgentBase Java-агенты Domino должны расширять класс AgentBase и реализовывать метод NotesMainQ «как точку входа в их функциональный код». Сам же класс AgentBase «расширяет» класс NotesThread (является наследником). Для получения объекта класса Session в агентах должен использоваться метод AgentBase.getSession. Спецификация класса AgentBase public class AgentBase extends NotesThread 1 protected Session m_session; public AgentBase(}; // Эти методы не могут быть перекрыты public final void startup(Agentlnf о info); public final void runNot.es () throws NotesException; // Метод NotesMain перекрывается в вашем классе. // Он должен содержать «функциональный код» агента. // Его вызов выполняется из AgentBase.runNotes, причем к этому моменту // -не только уже; выполнена инициализация для Domino, // но и фактически получен объект класса Session public void NotesMain( } ; public Session getSession( ) ; public boolean isRestricted(); public PrintWriter getAgentOutput(); public void setDebug(boolean debug); public void setTrace(boolean trace); public void dbgMsg (String msg, Print-Stream ps); public void dbgMsg(String msg, PrintWriter pw); public void dbgMsg(String msg); } Пример-шаблон 4. При создании Java-агента в интерфейсе Domino Designer автоматически генерируется шаблон его кода. Необходимый «функциональный код» агента должен быть вставлен вами «за строкой» // (Your code goes here). Таким же образом «должны оформляться» и агенты, создаваемые в других средах разработки. import lotus.domino.*; public class JavaAgent extends AgentBase { ,".,•-.. public void NotesMain() { try { Session session = getSession (); AgentContext agentCont&xt — session.getAgentContext(); // (Your code goes here) // Начало функционального кода агента String p = session . getPlatform () ; String u - session.getUserName(} ; System. out .printIn (".Session for user " + u + " on platform " + p); // Конец функционального кода агента } catch(Exception e) { e.printStackTrace(); } } } ' InterTrust Co. Тел. (095) 9567928 364 Встроенные кчассы LotusScript u Java Поскольку большинство примеров использования свойств и методов встроенных классов Domino, рассматриваемых далее в этой книге, выглядят именно таким образом, в этих примерах дается только добавленный «за строкой» // (Your code goes here) «функциональный код» агента. При этом так же предполагается, что переменные с именами session и agentContext «уже определены» точно так же, как и в этом шаблоне. В агентах, выполняющихся в клиенте Domino «на переднем плане», вывод в System.out и System.err «направляется в окно» Java debug console. В агентах, запускаемых на выполнение по расписанию или событию, вывод в System.out и System «направляется» в базу Log.nsf (Domino log). Агенты, выполняющие вывод HTML-кода «в броузер», должны создавать объект java.io.PrintWriter методом getAgentOutputQ класса AgentBase, Вывод, выполняемый в этот объект, например, методом println, «направляется в броузер». Этот же прием будет работать и при выполнении агента в среде клиента Domino, однако вывод, осуществляемый в объект, «направляется в окно» Java debug console. Пример-шаблон 5. Java-агент создает объект PrintWriter методом getAgentOutput и выполняет вывод HTML-кода «в броузер». Если «запустить» этот агент из броузера по URL наподобие http://domino500.inttrust.i'u:8080/Education/JavaLSExs.nsf/Java-PrintWriter?OpenAgent, в броузер будет передана строка "Session for user CN=Domino500/O=lnterTrustCorp/C=SU on platform Windows/32", где DominoSOO - имя сервера. При запуске в клиенте Domino этот же агент выведет в окно Java debug console строку "Session for user CN=Nikolay N. iontsev/O=InterTrustCorp/C=SU on platform Windows/32", где Nikolay N. lontsev - имя пользователя. import lotus.domino.*; impor-t Java . io . PrintWriter; public class JavaAgent extends AgentBase { public void NotesMain'J { try { Session session = qetSession(); PrintWriter pw = getAgentOutput(); String p = session.get Plat form{); String u = session.getUserName(}; pw.println{"Session for user " + u + " on platform " + p); } catch (Exception e) { e,printStackTrace(); } } } 3.2.3. Класс NotesFactory Хотя «корнем» в контейнерной иерархии back-end классов Domino считается класс Session, для получения объекта этого класса в Java-приложениях используются методы класса NotesFactory. Все методы класса NotesFactory являются статическими. Спецификация класса NotesFactory public class NotesFactory { // «Локальная» сессия - должен быть установлен Domino static public Session createSession() throws NotesException; /'/ «Удаленная» (ПОР) сессия с хостом как Anonymous или с аутентификацией static public Session createSession(String host) throws NotesException; static public Session createSession(String host, String user, String passwd) throws NotesException; © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (а)-формулы, LotusScript, встроенные классы LotusScript и Java 365 static public Session createSession(String host, String argsf ], String user, String passwd) throws NotesException; // «Удаленная» (ПОР) сессия с применением TOR static public Session createSessionWithlOR(String IOR) throws NotesException; static public Session createSessionWithlOR(String IOR, String user, String passwd) throws NotesException; static public Session createSessionWithlOR(String IOR, String args [ ], String user, String passwd) throws NotesException; // «Удаленная» (ПОР) сессия для апплета static public Session createSession(Java.applet.Applet app, String user, String passwd) throws NotesException; static public Session createSession(Java.applet.Applet app, org.omg.CORBA.ORB orb, String user, String passwd) throws NotesException; // Возвращает IOR для заданного хоста static public String getIOR(String host) throws Exception; } В приложениях, выполняющих «локальные» вызовы, для получения объекта класса Session должен использоваться метод NotesFactory.createSessionQ без параметров. Соответствующие примеры использования этого метода были рассмотрены в подразделе 3.2.1. В приложениях, выполняющих «удаленные» (НОР) вызовы, для получения объекта класса Session рекомендуется использовать методы NotesFactory.createSession(String host) или NotesFactory.createSession(String host, String user, String pwd). Параметр host обоих методов - «строковое представление» имени хоста сервера Domino. Параметр user - строка с именем пользователя - должен позволять серверу «обнаружить» в его адресных книгах соответствующий документ Person, а параметр pwd - пароль пользователя - должен быть таким же, как и пароль, содержащийся в поле Internet password этого документа Person. Если имя и пароль не были заданы, т.е. был использован NotesFactory.createSession(String host), приложению будет предоставлен анонимный доступ, если только анонимный доступ к серверу по портам ПОР не запрещен вовсе. В приложениях, выполняющих «удаленные» (ПОР) вызовы по порту задачи ОПОР с поддержкой SSL (Secure Socket Layer), для получения объекта класса Session должен использоваться метод NotesFactory.createSession(String host, String args[], String user, String pwd). Второй параметр метода - «массив строк» args[] - должен содержать первым элементом строку "-ORBEnableSSLSecurity". Пример-шаблон 6. Java-программа осуществляет «удаленные» вызовы к объектам на сервере Domino. При запуске программы в качестве первого параметра должно задаваться имя хоста, на котором находится сервер Domino. По выбору могут даваться третий и четвертый параметры - имя пользователя и его пароль. Если имя и пароль отсутствуют, к серверу возможен только анонимный доступ. Присутствие четвертого параметра требует «открытия сессии» по порту с поддержкой SSL и аутентификацией по имени и паролю. import lotus.domino.*; public class App4 implements Runnable { . - - " : • String host~null, user="", pwd-"", ssl=null; public static void main(String argv[]) • : i • • • . • ' • . if(argv.length < 1) . { • - • - . System.out.println("Need to supply Domino server host name"); return; } © InterTrust Co. Тел. (095) 9567928 366 Встроенные классы LotusScript и Java Арр4 t = new App4(argv); Thread nt = new Thread((Runnable)t); nt.start(); } public App4 (String argvt]) // Конструктор { host = argv[0]; i f (argv. length >•- 2) user = argv[l]; if(argv.length >= 3) pwd = argv[2]; if (argv. length >= 4) ssl •— argv[3]; } public void run() { tгу{ Session s = null; String args[] = new String[1]; args[0] = "-ORBEnableSSLSecurity"; if (ssl == null) //Вез SSL { s = NotesFactory,createSession(host, user, pwd); ) else // SSL { s = NotesFactory,createSession(host, args, user, pwd); } String p = s.getPlatform(); String u = s.getUserName(); System.out.println("Remote session for user " + u + " on platform " -t p) ; } . . . catch(NotesException e) { System.out.println(e.id + " " + e.text); e .printStackT.race ( ) ; } catch (Exception e) { e.printStackTrace(); } } . . . . . . t Результат выполнения этой программы может выглядеть следующим образом. D: \JavaEx\BookExamples\Templates>java App4 dominoSOO NIontsev password Remote session for user CN=Nikolay N. Iontsev/0=InterTrustCorp/C=SU on plat form Windows/32 Заметим, что для получения объекта класга Session в агентах используется метод AgentBase.getSessionQ. В апплетах же для получения объекта класса Session применяются методы AppletBase.openSessionQ или AppletBase.openSession(String user. String pwd), а для «закрытия сессии» метод AppletBase.closeSession(Session session). 3.2.4. Классы AppletBase и JAppIetBase Апплет, осуществляющий обращения к объектам Domino, должен «расширять» класс AppletBase или JAppIetBase и замещать в своем базовом классе все или только необходимые методы notesAppletlnitQ, notesAppIetStartQ, notesAppletStopQ и notesAppletDestroyQ. Эти методы подобны методам initQ, start(), stop() и destroyQ «обычных» апплетов. Другие методы «обычных» апплетов, в частности getAppletlnfoQ, getParameterlnfoQ, а так же унаследованные от суперклассов класса Applet методы paintQ, printQ, getParameter(), © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @гформулы, LotusScript, встроенные классы LotusScript и Java getCodeBaseQ, getDocumentBaseQ, showStatus(), getAppletContext() и др., AppletBase или JAppletBase «не перекрыты». 367 в классах Метод notesApplet!nit() (аналог init()) вызывается при первой загрузке апплета в броузер. Обычно содержит код инициализации апплета. Метод notesAppletStartQ (аналог startQ) вызывается, когда апплет становится «видимым» и должен приступить к выполнению своей работы. Метод paintQ вызывается, когда апплет «должен отобразить себя на экране». Метод notesAppletStopO (аналог stopQ) вызывается, когда апплет становится «невидимым» (например, пользователь «прокрутил» изображение апплета за пределы окна броузера.) и «должен приостановить» выполнение апплетом своей работы. Метод notesAppletDestroyO (аналог destroyQ) вызывается перед выгрузкой апплета из броузера и должен освободить все ресурсы, захваченные апплетом, за исключением ресурсов памяти. Для разработчика апплета, расширяющего класс AppletBase или JAppletBase, в основном нет никаких различий между «локальными» и «удаленными» вызовами. Сами классы AppletBase или JAppletBase автоматически выполняют «локальные» вызовы, если апплет выполняется в среде клиента Domino, и «удаленные» вызовы, когда апплет выполняется в броузере. Спецификация класса AppletBase public class AgentBase extends Applet: implements DominoAppletBase { public AppletBase(); ,// Методы getSession и openSession возвращают объект класса Session. // В варианте с параметрами апплет получает доступ к серверу под именем // user с паролем pwd, в варианте без параметров - как Anonumous. // Метод closeSession закрывает открытую сессию. public Session getSession () throws N'otesException; public Session getSession(String user, String pwd) throws NotesException; public Session openSession() throws NotesException; public Session openSession(String user, String pwd) throws NotesException; public void clcseSession(Session session) throws NotesException; ,/,/ Выполняет инициализацию апплета public final void init(); public void notesAppletlnit(); // Выполняет запуск апплета public final void start{); public void notesAppletStart(); // Выполняет останов апплета public final void stop(); • * public void notesAppletStop { } ; ..• // Выполняет завершение апплета public final void destroy(); public void notesAppletDestroyO; // Возвращает true, если апплет может выполнять локальные обращения или // false, если не может public boolean isNotesLocal() ; } Спецификация класса JAppletBase отличается от приведенной лишь тем, что класс JAppletBase «расширяет» класс JApplet и «импортирует» пакет com.sun.java.swing. © InterTrust Co. Тел. (095)9567928 Встроенные классы LotusScript и Java 368 Для создания объекта класса Session, обеспечивающего доступ к классам Domino, такой апплет должен использовать методы getSessionQ или getSession(String user, String pwd) или аналогичные им методы openSessionQ или openSession(String user, String pwd), а для «закрытия сессии» метод closeSessioii(Sessior) session). Шаблон-пример 7. Простейший апплет, осуществляющий обращения к объектам Domino, может выглядеть следующим образом. .;•-.. import lotus.domino.*; public class DIlOFAppletl extends AppletBase { Java.awt.TextArea ta; Session s; public void notesAppletlnit{) { set-Layout (null) ; setSize (600, 50} ; t a r= new j ava . awt. Text Area () ; ta.setBounds(0,0,599,49); add(ta); ta.setEditable(false); setVisible(true); } public void notesAppletStartО { try { // Can also do // s = this.openSession("NIontsev","Password"); s = this.openSession(); if (s == null) { //not able to make the connection, warn user ta.append("Unable to create a session with the server"); return; } String p = s . getPlatform (} ; String u -• s . getLIserName ( } ; ta.append("Session for user "+ ц + " on platform " + p); } catch (Exception e) { e .printStackT'race (} ; } i public void notesAppletStopO { try { this.closeSession(s); } catch (Exception e) { e , printStackT'race ( ) ; }} } Пример 8. Этот апплет выполняет обращения к объектам на сервере Domino не только из метода notesAppletStart, но и в обработчике события нажатия кнопки - action. Поскольку обработчик события выполняется в отдельном потоке, в случае выполнения апплета в среде клиента Dornino («локальные» вызовы) должен выполняться код инициализации и завершения Domino. Однако при «удаленных» вызовах такое, напротив, не должно происходить. i m p o r t l o tu s . do m i no .* ; import j ava.awt.*; i mp о r t: j a v a . a pp 1 e t. App let; public class DlIOPApplet.2 extends AppletBase { © InterTrust Co. Тел. (095) 9567928 Lotus Domino К, 5: (^-формулы, LotusScript, встроенные кшссы LotusScript и Java private Button Ь2; ' _ private String text = ""; Graphics gl; int j = 0, k = 0; Dimension dScreen; public Java.awt.TextArea ta; public Session s; . .. • ;• 369 •• . .. public void notesAppletlnit () ' = • ' -''V-">K- "."••^"^ •-,'<*"<: X>> • •"• •'•"-••-.:-• .... . { gl = getGraphics(); dScreen - this.getToolkit().getScreenSize(); b2 = new Button("b2 Java Notes Classes"); add(b2); я.-. •• b2.requestFocus(); ta - new Java.awt.TextArea(15,30); add(ta); } public void paint(Graphics g) ; т b2.move(0, 0); ta.move(200,0); } . ' ' public void notesAppletStart() i . • try -•. . . . .. { s = this.openSession(); ta.append("User " + s.getCommonUserName()+ "\n"); } catch (NotesException e) { text :=; e. id + " " + e.text; } catch(Exception e){ e.printStackTrace (); } }• . , / ' . . . . . public boolean action(Event e, Object o) • f : if(e.target instanceof Button) _ { ^ " text = ""; if(e.target.equals(b2) ) { this.b2Test (); } ta.append(text + "\n"); } ' . ' . . . return true; } ; . ; • . // Jjiva Notes Classes public void b2Test() { try { , ' ' ., . .- : . if (isNotesLocal() == true) NotesThread.sinitThread(); text = "User " + s.getCommonUserName(); } ' " ' • ' ' ' catch(NotesException e) { text - e.id + " " + e.text; } catch(Exception e) { e.printStackTrace(); } finally { if (isNotesLocal() == true) NotesThread.stermThread(); } } ......... - - •- - } // end of Applet • ... , . © InterTrust Co. Тел. (095) 9567928 370 Встроенные классы LotusScript u Java 3.2.5. Размещение CORBA-анплетов на сервере Domino Процесс помещения апплета из примера 7 в базу данных на сервере Domino может быть приблизительно следующим. В документе в поле типа RichText (и аналогично в форме или на странице) выбором в меню Create-Java Applet создается новый апплет. Рис. 3. 7 Окно Create Java Applet Кнопкой Locate «вызывается» окно, в котором выбираются дополнительные файлы, загружаемые вместе с апплетом. В данном случае архив NSCO.jar, хотя рациональнее использовать его «сжатую» версию NSCOC.jar. Рис. 3.8 Окно Locate Java Applet Files В окне свойств апплета выбирается опция Applet uses Notes CORBA classes. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5; @гформулы, LotusScript, встроенные классы LotusScript и Java PMC. 3.9 371 Свойства апплета В клиенте Domino или броузере этот апплет выглядит приблизительно следующим образом. " •02. DHOP Applet Template Рис, 3.10 «Внешний вид» апплета из примера 7 . . Рассмотрим тег <APPLET>, автоматически генерируемый задачей HTTP для данного апплета. <APPLET WIDTH="600" HEIGHT="50" CODEBASE^"/OursDBs/WorkDatabases/Education/JavaLSExs.nsf/79866f57dc2229d4с 32567480043cf8e/8a4ddf721bf778c7c32567700058fda3/$FILE" CODE="DIIOPAppletl.class" ALT="Loading..." ARCHIVE="NCSO.jar,NCSOC.jar"> <PARAM NAME="NOI__IOR" VALUE-"TOR:010000002900000049444c3a6c6f7475732f646f6d696e6f2f636f7262612f4 94f626a6563745365727665723а312е3000000000010000000000000054000000010101000 dOO00003139352e3230382e36382e380000acf6310000000438353235363531612d6563363 82d313036632d656565302d303037653264323233336235004c6f7475734e4f49010001000 00000000000"> <PARAM NAME="NOI_COOKIE_URL" VALUE="/OursDBs/WorkDatabases/Education/JavaLSExs .nsf'PGetOrbCookie"> </APPLET> , . ' , • , В нем нет ничего необычного, за исключением лишь двух параметров NOI__IOR и NOI_COOKIE_URL, автоматически генерируемых задачей HTTP, если в свойствах апплета была выбрана опция Applet uses Notes CORBA classes. Для уяснения смысла параметра NOMOR придется обсудить еще одно заимствованное из CORBA понятие - IOR (Interoperable Object Reference). Это ссылка на объект, по которой клиентский брокер запросов может «найти» компьютер, на котором находится объект, и передавать этому компьютеру запрос на вызов необходимого метода. В частности, IOR включает TCP/IP-адрес компьютера и номер порта, на котором брокер запросов сервера ожидает запросы, некоторый уникальный идентификатор для процесса сервера и ссылку на ) InterTrust Co. Тел. (095) 9567928 372 Встроенные классы LotusScript и Java запрашиваемый объект. Когда брокер запросов сервера получает ПОР-запрос, содержащий 1OR необходимого клиенту объекта, он «загружает» этот объект в свою виртуальную память или создает его экземпляр и возвращает клиенту ссылку на этот объект. После этого клиент может посылать запрос на вызов метода «непосредственно объекту». Параметр NOIJOR содержит ни что иное, как строку 1OR (Interoperable Object Reference) для задачи DIIOP данного сервера, позволяющую открыть с ней сессию. В своем методе notesAppletStartQ для получения объекта класса Session апплет вызывает метод AppletBase.getSession(). Этот метод сам реализуется посредством вызова NotesFactory.createSession(String IOR), которому необходима строка 1OR. Конечно, строку IOR можно было бы получить вызовом NotesFactory.getIOR(String host), но последнее будет означать «пусть небольшой, но все же» HTTP-запрос типа GET на HTTP-сервер. Чтобы по возможности не выполнять такого запроса, в реализации AppletBase.getSessionQ сначала проверяется, не передана ли строка 1OR апплету в качестве значения параметра NOIJOR, и, если передана, ее значение «сразу» используется в методе NotesFactory.createSession(String IOR). Параметр NO1_ COOKIEjURL не менее важен - он позволяет апплету сообщать задаче ОПОР, какой пользователь «находится» на клиентском компьютере. Предположим, что в списке управления доступом базы данных, содержащей апплет, для -Default- выбрано No Access (нет доступа). Введя URL в окне броузера, клиент получает от задачи HTTP запрос на ввод имени пользователя и пароля, чтобы сервер мог его аутентифицировать и затем проверить, имеет ли данный пользователь доступ к базе. Предположим, что задача ОПОР не имела бы никакого автоматического опознавательного механизма. Когда апплет, теперь уже разгруженный в виртуальную машину броузера, попытался бы открыть сессию с задачей ОПОР, его «пользователя» пришлось бы вновь аутентифицировать, возможно, повторным вводом имени и пароля. Поэтому, генерируя по запросу броузера HTML-код страницы с CORBA-апплетом, задача HTTP добавляет в тег <APPLET> параметр NOI_COOKIE_URL, содержащий ссылку на аутентифицированное имя пользователя и IP-адрес компьютера, на который передан этот HTML-код. Затем, когда этот апплет обращается к задаче ОПОР на этом сервере, метод AppletBase.getSessionQ передает значение параметра NOI_COOKIE_JJRL задаче ОПОР, и по нему задача ОПОР «узнает», какой пользователь «находится» на клиентском компьютере. 3.2.6. Сервлеты, использующие объекты Domino Сервлет (servlet) представляет собой специальное приложение, написанное на языке Java и выполняющееся на Web-сервере, обеспечивающем поддержку сервлетов. Когда Web-сервер принимает от клиента запрос, IJRL которого «указывает на» сервлет, сервер выполняет сервлет, и вывод сервлета отправляется клиенту. Поведение сервлета во многом подобно поведению CGl-программы. Одно из основных отличий состоит в том, что сервлет не нуждается в загрузке при каждом обращении к нему - загрузка сервлета выполняется только один раз, обычно при первом обращении к нему. Domino, точнее серверная задача HTTP, может загружать и выполнять сервлеты, удовлетворяющие Java Servlet API Specification Version 2.0 от Sun Microsystems, Inc. Для разработки сервлетов необходимо получить копию Java Servlet Development Kit с сайта JavaSoft (http://www.javasoft.com/products/servlet/index.html). Краткое введение в сервлеты Сервлеты должны реализовывать интерфейс javax.servlet.Servlet. Обычно этого досчитают, создавая класс-потомок javax.servlet.GenericServlet или javax.servlet.HttpServIet. Оба эти базовых класса реализуют интерфейс Servlet, причем HttpServlet сам является потомком GenericServiet. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные массы LotusScript и Java 373 Когда сервлет загружается сервером, в сервлете происходит вызов метода initQ. Метод initQ вызывается только один раз. После того, как сервер загрузит и «инициализирует» сервлет, последний становится способен обрабатывать запросы клиентов. Каждый запрос клиента приводит к вызову в сервлете метода serviceQ. Метод serviceQ должен быть написан с учетом параллельного выполнения потоков (thread-safe manner), поскольку каждый новый запрос порождает новый поток, выполняющий в себе метод serviceQ. Например, если метод serviceQ изменяет значение некоторого поля в объекте сервлета, доступ к этому полю должен быть синхронизирован. Если же по каким -то соображениям метод serviceQ не должен выполняться в разных потоках, то сервлет должен реализовать интерфейс SingleThreadModel. import javax.servlet.* import j ava.io . * public class MyServletl extends HttpServlet { /* метод service!) будет вызываться из многих потоков */ } import; ~j avax . servlet . * import j ava.io.* public class MyServlet2 extends HttpServlet implements SingleThreadModel { /* метод service{) может вызываться только в одном потоке */ } Сервлет обычно функционирует на сервере до тех пор, пока функционирует сервер или пока его не выгрузят. В этом случае в сервлете вызывается метод destroyQ. Метод destroyQ вызывается только один раз, и должен «дождаться» завершения или принудительно завершить все потоки, выполняющие метод serviceQ, и освободить все выделенные сервлету ресурсы. Только после этого сервлет может быть вновь загружен и инициализирован. Еще одним стандартным методом сервлета является getServletlnfoQ. Он должен возвращать строку (String), содержащую описание сервлета. Возвращаемый текст обычно используется средствами управления сервлетами на сервере. «Не перегруженный» метод getServletlnfoQ возвращает пустую строку. Если сервлет является наследником класса HttpServlet, часто перегружают не сам метод serviceQ, а другие методы, вызываемые «родным» методом serviceQ в зависимости от запросов клиента: * doGetQ - вызывается для обработки запросов GET, условный GET и HEAD (клиент запрашивает необходимые ему данные, а сервер (сервлет) возвращает клиенту запрошенную им информацию); » getLastModifiedQ - вызывается при обработке запросов GET, условный GET и HEAD и возвращает время последней модификации запрошенного клиентом ресурса; ;' » doPostQ - вызывается для обработки запроса POST (клиент заполняет форму и передает введенные данные на сервер, сервер (сервлет) принимает и обрабатывает данные и обычно отвечает клиенту подтверждением приеме данных). «Не перегруженные» методы doGetQ и doPostQ возвращают код ошибки 400 (BAD_REQUEST - «Плохой» запрос от клиента), а «не перегруженный» getLastModifiedQ -отрицательное число, означающее, что время последней модификации неизвестно, а потому не должно применяться в запросе условный GET и при кэшировании. Методы serviceQ, doGetQ и doPostQ получают два параметра: объекты классов HttpServletRequest и HttpServletResponse, метод getLastModifiedQ - один параметр: объект класса HttpServletRequest. Эти объекты поддерживают соответственно интерфейсы javax.servlet.http.HttpServletRequest и javax.servlet.http.HttpServletResponse, которые в свою очередь «расширяют базовые» интерфейсы javax.servlet.ServietRequest и javax.servlet.ServletResponse. i InterTrust Co. Тел. (095) 9567928 374 Встроенные классы LotusScript и Java Класс HttpServletRequest инкапсулирует передачу информации от клиента к сервлету. Методы и свойства ServletRequest позволяет сервлету получать такую информацию, как имена параметров, переданных клиентом серверу, схему, использованную клиентом, имена хостов клиента и сервера, а также входной поток ServletlnputStream, «из которого» сервлет получает данные, переданные клиентом при использовании метода POST. Класс HttpServletResponse инкапсулирует передачу информации от сервлета к клиенту. Методы и свойства ServletResponse позволяет сервлету «отвечать» клиенту: задать М1МЕ-тип «ответа» и длину содержимого (content length), а так же получить выходной поток ServletOutputStream, в который сервлет должен записывать передаваемые клиенту данные. Пример 9. Самый простой сервлет из Java Servlet Development Kit. /* * @(#)HelloWorldServlet.Java 1.9 97/05/22 * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved. +/ import java.io.*; import javax.servlet.*; import javax,servlet.http.*; public class HelloWorldServlet extends HttpServlet { .' public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, lOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); out.println("<html>"); out .printIn ("<head><title>Hello World</titlex/head>") ; out.println("<body>"); out .println ("<hl> -- Hello World -- </.hl>") ; out.println("</body></html>"}; } public String getServletInfо() { return "Create a page that says <i>Hello World</i> and send it back"; } } © InterTrust Co. Тел. (095) 9567928 • Lotus Domino R, 5: (ад-формулы, LotusScript, встроенные классы LotusScript и Java 375 Настройка поддержки сервлетов задачей HTTP К вопросу поддержки сервлетов задачей HTTP имеет отношение группа полей Java Servlets, находящихся на закладке Internet Protocols - Domino Web Engine документа Server. SERVER NotesScv4GQ/JrHe» Гг-л',»<" Basics I Security j Ports Serve-T^ks | Internet Protoi i 1 Miscellaneous Ttansacdonal Logging j Administrate,i , HTTP J Domino Web Engine | HOP ] LDAP ] NN7P Session authentication I die session timeout: i ikibird ,_»j *' 10.. r minutes Pitc. 3.12 Фрагмент документа Server - группа полей Java Servlets Java servlet support - три варианта поддержки сервлетов задачей HTTP: * None (по умолчанию) - отсутствует, задача HTTP не загружает виртуальную машину Java (JVM) и Servlet Manager; * Domino Servlet Manager - стандартная, задача HTTP загружает JVM и Domino Servlet Manager; * Third Party Servlet Support - используется Servlet Manager от другого производителя, например, IBM's WebSphere; задача HTTP загружает JVM, но не загружает Domino Servlet Manager. Servlet URL path - префикс «пути» в URL, «сигнализирующий» задаче HTTP, что URL указывает на сервлет. По умолчанию /servlet. Class path - список, содержащий относительные (относительно каталога данных Domino) или абсолютные пути к каталогам или файлам архивов, в которых Servlet Manager должен осуществлять поиск классов самих сервлетов и необходимых им классов. По умолчанию domino\servlet. Servlet file extensions - список, содержащий «расширения», «сигнализирующие» задаче HTTP, что URL указывает на сервлет. Каждое «расширение» в этом списке должно быть определено в файле servlets.properties в директиве extension и должно однозначно «указывать» на единственный сервлет. Подробнее рассматривается ниже. Session state tracking - относится только к сервлетам, реализующим интерфейс HttpSession. Выбор Enabled (значение по умолчанию) требует, чтобы Servlet Manager «отслеживал» объекты класса HttpSession, которые «были неактивны» в течении заданного интервала времени. Как только Servlet Manager обнаруживает такую «продолжительно неактивную сессию», он вызыва ет для ее объекта метод HttpSession.invalidateQ, «сообщая» тем самым сервлету, что сессия завершается. Выбор Disabled запрещает Servlet Manager контролировать «продолжительность неактивности» этих объектов. Idle session timeout - относится только к сервлетам, реализующим интерфейс HttpSession, и задает продолжительность «интервала неактивности» в минутах (по умолчанию 30). Maximum active sessions - применимо только к сервлетам, реализующим интерфейс HttpSession, и задает максимально допустимое количество «конкурирующих сессий» -объектов класса HttpSession. По умолчанию 1000. Когда количество «конкурирующих © InterTrust Со, Тел. (095) 9567928 376 # Встроенные классы LotusScript и Java сессий» превышает заданное, Servlet Manager начинает «закрывать сессии», имеющие наибольший «интервал неактивности». Sessions persistence - применимо только к сервлетам, реализующим интерфейс HttpSession. Выбор Enabled означает, что перед завершением задачи HTTP Servlet Manager должен сохранить состояние объектов класса HttpSession в файле sessdata.ser в каталоге данных Domino, а при очередном запуске задачи HTTP вновь создать эти объекты класса HttpSession с восстановлением их состояния из файла sessdata.ser (сериализация объектов, реализующих интерфейс java.io.Serializable). Выбор Disabled (по умолчанию) запрещает сериализацию объекты класса HttpSession. Файл servlets.properties представляет собой текстовый файл, расположенный в каталоге данных Domino, и содержащий набор директив четырех типов. Директивы «чувствительны к регистру». В файле допустимы строки комментариев - они должны начинаться символом #. Директива servlet.<alias-name>.code=<class-name> определяет алиас alias-name (в нем не должна встречаться «точка») для сервлета class-name. Например, директива servlet.SQLQuery.code=sql.database.query.Servlet назначает сервлету sql.database.query.Servlet алиас SQLQuery. В результате этот сервлет становится доступен по URL http://<hostname>/servlet/SQLQuery?month=june. Заметим, что Domino Servlet Manager по соображениям безопасности не загружает сервлеты, в именах которых содержится «точка» - для таких всегда должен быть назначен алиас. Директива servJet.<a!ias or class name>.extension=<extension> <extension> ... задает список «расширений» для сервлета. «Расширения» в директиве отделяются друг от друга пробелами. Например, директива servlet.SQLQuery.extension=sql sq обязывает Servlet Manager вызывать сервлет SQLQuery по любому URL, содержащему «расширения» "sql" или "sq", в частности, http://<hostiiarne>/query.sql?month=june. Все «расширения», встречающиеся в файле servlets.properties, должны однозначно определять сервлеты и должны быть дополнительно перечислены в поле Servlet file extensions документа Server. Директива servlet.<alias or class name>.initArgs=<namel>=<valuel>,<name2>=<value2>... позволяет сообщить сервлету значения «инициализационных» параметров. Сервлет обычно получает эти значения методом ServletConfig.getlnitParameterQ в своем методе init(). Например, servlet.SQLQuery.initArgs=target=db2,user=Domino,cacheSize=30 Директива servlets.startup=<alias or class> <alias or class> ... требует, чтобы загрузка перечисленных в ней сервлетов выполнялась при запуске задачи HTTP, а не при первом обращении к сервлету. как происходит по умолчанию. Имена алиасов (или классов) разделяются в директиве пробелами. Например, файл servlets.properties может выглядеть следующим образом. # Properties for the sql servlet servlet,SQLQuery.code=sql.database.query.Servlet servlet.SQLQuery.extension=sql servlet. SQLQuery . init.Args=cache=30 # Properties for the mail servlet servlet. MailServlet. initArgs-mime-enabled, sm.ime=disabled tt Both servlets should be loaded at startup servlets.startup=SQLQuery MailServlet # end of file Domino Servlet Manager не выполняет загрузку классов, которые используют внешний код на Си (native code), создают собственные загрузчики классов или выполняют другие © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 377 «ограниченные» операции. Если ваш сервлет использует класс, который не может быть загружен Domino Servlet Manager, можно попытаться загрузить его загрузчиком классов виртуальной машины Java, используемой задачей HTTP (Domino JVM). Загрузчик классов Domino JVM обычно осуществляет загрузку классов из стандартных Java-архивов, входящих в состав Domino, в частности, из пакетов Java.* и lotus.* . Вы можете «форсировать» загрузку своих классов, переместив их «из путей» Domino Servlet Manager «в пути» Domino JVM, которые задаются в переменной JavaUserClasses файла NOTES.INI сервера. Команда консоли сервера Tell HTTP Restart «реинициализирует» загруженные сервлеты: Domino Servlet Manager вызывает для каждого загруженного им сервлета метод destroy(), а затем, обычно при «первом последующем» обращении-к сервлету, метод init(). Выгрузки и повторной загрузки класса сервлета при этом не происходит. Выгрузка и повторная загрузка классов сервлетов происходит при перезапуске задачи HTTP (команды консоли Tell HTTP Quit, затем Load HTTP). Именно это должно выполняться, когда в код сервлета (файл .class) были внесены изменения. Сервлет, осуществляющий локальные обращения к объектам Domino Поскольку класс сервлета обычно «расширяет» класс HttpServlet. а обращения сервлета к объектам Domino «локальны», в коде такого сервлета вы должны или реализовывать интерфейс Runnable и создавать объект класса NotesThread (подобно примеру-шаблону 2), или пользоваться статическими методами sinitThread и stermThread. Выполнение такого сервлета происходит «под ID-файлом» сервера Domino, что, говоря вообще, может расцениваться как нарушение безопасности сервера. Шаблон-пример 10. Простейший сервлет, осуществляющий локальные обращения к объектам Domino «техникой» sinitThread и stermThread, может выглядеть следующим образом, import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import lotus.domino.*; ' ' ' • public class Servlet1 extends HttpServlet { ''""•' public void doGet(HttpServletRequest req, HttpServletResponse resp) ' ' { ' try { - . •• : ' •-•••• • • - - ' • - NotesThread.sinitThread(); - > :-•resp. setContentType ( "text/html" )/ Session s = NotesFactory.createSession(); ServletOutputStream out = resp.qetOutputStream(); out.printIn{"<html>"); out. print In ( "< headxt it 1 e>UserN ame &Plat form</title ></head>" ) ; out.println("<body>"); out.print In("Session for " + s.getUserName() + ...-. " on platform " + s . getPlatf orm () ) ; out .println ("</bodyx/html>") ; '...•}-. - . , . . . . catch(Exception e) { e.printStackTrace(); } finally { NotesThread.stermThread(); } "•) • " . . • . - • . . . . . . ' . public String getServletlnfо() "'{' ' • :. -••- © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 378 return "Servlet to display server name & platform"; } , : } Рис, 3.13 «Отклик» этого сервлета в броузере 3.2.7. Класс Base - общие методы для встроенных классов Domino Все рассматриваемые далее встроенные классы Domino для Java являются производными (наследуются) от класса Base, В классе Base имеются методы, «общие» для встроенных классов Domino. Метод recycle - «освободить память, занимаемую СРР-объектом в кеше» void Object.recycleQ void Session. recycle(/ava. util. Vector objects) Большинство классов Domino, находящихся в «контейнерной иерархии от Session и ниже», имеют метод recycle. Кроме того, класс Session имеет вариант метода recycle, аргументом которого является вектор объектов - он наиболее эффективен при «удаленных вызовах». Метод recycle освобождает память, занимаемую в кеше Domino СРР-объектом, соответствующим объекту Domino. Появился метод в Domino с версии 4.61 для предотвращения ситуации переполнения кеша СРР-обьектов. Все дело в том, что свойства и методы классов «внутри» Domino реально реализованы на языке C++, а их вызов из Java-приложения (как, впрочем, и из скрипта), влечет вызов соответствующего метода на языке C++ (native call, см. Рис. 3.2 и Рис. 3.1). Создание нового объекта в приложении на Java влечет создание СРР-объекта, память для которого выделяется не Java-машиной, а соответствующим конструктором из реализации класса на языке C++ в специальном кеше Domino. При этом Domino (при локальных вызовах как сервер, так и клиент, при удаленных -сервер) сохраняет СРР-объекты в кеше, чтобы было возможным повторно использовать их при последующих обращениях, не создавая заново. В большинстве случаев, как в однопоточных, так и в многопоточных агентах и приложениях, такое поведение позволяет ускорить обработку. Но размер кеша Domino для СРР-объектов не безграничен, и в агентах и приложениях с большим количеством объектов иногда возникает ситуация нехватки памяти. Наиболее часто такое встречается при обработке в цикле большого количества (несколько тысяч) документов из коллекции или вида или при создании в цикле большого количества новых документов. Сборщик мусора Java не может освобождать память, занимаемую СРР-объектами - она находится «вне его области компетенции». Чтобы освобождать память, занимаемую СРР-объектами Domino, в Java используют метод recycle. Аналогичная ситуация может возникать и в LotusScript, где «для борьбы с нею» применяют явные вызовы деструктора delete для © InterTrust Со. Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 379 «ненужных» объектов, однако полной аналогии между явным вызовом деструктора в LotusScript и метода recycle в Java нет. Перечислим основные принципы использования метода recycle. • • • • • • • • • • Не следует применять recycle, если не возникает проблем с нехваткой памяти. Типичные «места кода», где целесообразно применять recycle - циклы по коллекциям документов или по документам из вида. Вы должны быть уверены, что ни к самому объекту, ни к содержащимся в нем объектам не происходит обращений после того, как для объекта был выполнен recycle. Метод recycle для объекта вызывает «серию вызовов recycle» для содержащихся в нем объектов. Не применяйте recycle для объектов, которые существуют, но создавались «не вами» например, которые были получили из «контекста агента», в частности для объекта текущей базы данных, полученной методом CurrentDatabase. Будьте крайне аккуратны при использовании recycle в случае многопоточного приложения с «локальными» вызовами или агента. Вызывать метод нужно обязательно в том же потоке, в котором этот объект был создан, и только тогда, когда этот объект гарантированно не будет более использоваться другим потоком. Вызывать метод recycle для объекта Session следует не только в том же потоке, где объект был создан, но и после завершении всех остальных потоков. В случае «удаленных» вызовов таких ограничений нет. В многопоточном приложении с «локальными» вызовами или агенте безопасно применять метод recycle к объекту класса Database (представляет базу данных) или содержащимся в нем объектам лишь тогда, когда с этим объектом Database работают только из одного потока. В противном случае recycle, вызванный из одного потока, «грубо удалит» СРР-объект, в результате чего при попытке использовать объект в другом потоке, скорее всего, возникнут исключения наподобие обращения по нулевому указателю (null pointer). Однако в многопоточном приложении с «локальными» вызовами или агенте можно «взять за правило» получать в каждом потоке свой объект класса Session, а от него - свой объект класса Database. Это позволит безопасно применять метод recycle к объекту класса Database или содержащимся в нем объектам в каждом потоке, даже если объекты Database разных потоков связаны с одной и той же базой данных. Если ваш Java-агент должен выполняться как асинхронный Web-агент (в NOTES.INI сервера имеется переменная DOMINOASYNCHRONIZEAGENTS=1), методы recycle рекомендуется применяться всякий раз, когда это возможно. Это минимизирует набор рабочих СРР-объектов агента, который совместно использует ресурсы с другими выполняющимися агентами. Все СРР-объекты автоматически освобождаются по завершении агента или приложения (но не потока). Метод toString - «текстовое представление объекта» String text = OZy<?e?.toString() Метод toString, наследуемый всеми классами от java.lang.Object, «перекрыт» в следующих классах Domino: ACLEntry (как gefName), Agent (как getName), AgentContext (как getEffectiveUserName), Database (как getFilePath), DateRange (как getText), DateTime (как getLocalTime), DbDirectory (как getName), Document (как getUniversallD), EmbeddedObject (как getName), Form (как getName), Item (как getName), Log (как getProgramName), Name (как getCanonical), Session (как getUserName), View (как getName), ViewColumn (как getTitle). © InterTrust Co. Тел. (095) 9567928 380 Встроенные классы LotusScript и Java Метод getURL - «получить URL объекта» •;..•..- • String ml = Ofyect.getURLO Метод возвращает URL объекта. Определен для объектов классов Agent, Database, Document, Form, Session (при локальных вызовах «пустая строка») и View. Пример. Этот Java-агент выведет на консоль следующее. Database db=agent.Context . getCurrentDatabase {) ; Agent ag = agentContext.getCurrentAgent(); System., out . print In ("Session " + session . toString {) + "\n\t URL "+session,getURL();; System.out.println("Database "+db.toString ()+"\n\t URL "+db.getURb()); System, out. .println ( "Agent "+ag. toString {) + "\n\t URL "+ag.getURL() ) ; Session CN=Nikolay N. lontsev/O=InterTrustCorp/C=SL) URL Database WorkDatabases\Educatioo\JavaLSExs.nsf URLnotes://CN=NotcsSrv400/O=lnterTrustCorp/C=SU/_C32S6714004F334B.nsf?OpenDatabase Agent Java-getUrl URLnotes://CN=NotesSrv400/O=lnterTrustCorp/C=SU/_C3256714004F334B.nsf/ ODOC732D91A01605C32567A100259555?OpenAgent Интерфейс java.beans.Visibiiity Все классы Domino реализуют интерфейс java.beans.Visibiiity, но «сконфигурированы как невидимые»: метод needsGuiQ всегда возвращает false, а метод avoidingGUIQ - всегда true. •j © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулм, LotusScript, встроенные классы LotusScript и Java 381 3.3. «Сессия» и «контекст агента» - классы [Notes]Session и AgentContext Класс [NotesJSession является «корневым» в «контейнерной» иерархии встроенных классов. Объект класса [Notes]Session представляет текущую сессию (сеанс). Он обеспечивает доступ к переменным среды, адресным книгам, текущей базе данных и текущему агенту, позволяет получать информацию о текущем пользователе, текущей платформе и номере реализации Notes, используется для «отметки» обработанных агентом документов и обеспечивает возможность создания объектов некоторых других классов без явного создания объектов, являющихся контейнерами для создаваемых. Класс AgentContext присутствует только в составе встроенных классов Java и инкапсулирует те свойства и методы, которые присущи только выполняющемуся агенту и не имеют смысла в иных контекстах. Все свойства и методы класса AgentContext так или иначе доступны и в LotusScript, чаще всего в составе класса NotesSession и NotesDatabase, но всегда с четкой оговоркой допустимого контекста применения. Вероятно, последнее и послужило причиной выделения присущих только выполняющемуся агенту свойств и методов в отдельных класс в Java. «Контейнерная иерархия» LotusScript New _ > NotesSession ~> NotesDbDirectory NotesDatabase NotesAgent NotesDocument NotesDocumentCollection NotesRichTextStyle NotesRichTextParagraphStyle NotesNewsLetter NotesLog NotesDataTime NotesDateRange Noteslnternational NotesNarne NotesTimer Java AgentBase — > Session — > AgentContext AppletBase AgentContext — > Agent NotesFactory DbDirectory Database Registration Document Documented lection RichTextStyle RichTextParagraphStyle News Letter Log DataTime DateRange International Name В LotusScript для получения доступа к текущей сессии необходимо методом New создать объект класса NotesSession. . . Dim variableName As New NotesSession или © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 382 ^ Set notesSession = New NotesSession Поскольку выполнение любого скрипта всегда происходит в рамках одной сессии, очередной вызов метода New для NotesSession будет всегда возвращать тот же самый объект. Пример. Скрипт создает новый объект класса NotesSession и использует его для доступа к текущей базе (базе, в которой выполняется скрипт). Такая техника позволяет избегать использования конкретных имен серверов и файлов баз в скриптах. Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase If ( db.IsOpen ) Then Messagebox db.Title Eise Call db.Open( "", "" ) Messagebox db.Title End If Различные способы создания объекта класса Session в Java были рассмотрены в главе 3.2. 3.3.1. Свойства Свойство AddressBooks - «доступные адресные книги» LotusScript: Java: ... . . . : . . . . ; • • ........ . ... notesDatabaseArray - notesSession.AiidressBooks java.util. Vector database Vector -- Sessww.getAddress'BooksQ Адресные книги, доступные во время выполнения. В LotusScript возвращается массив с элементами класса NotesDatabase, в Java - объект класса java.util.Vector с элементами класса Database. Если выполнение происходит на станции, свойством обычно возвращаются как личная адресная книга, так и общие. Если же выполнение осуществляется на сервере, обычно возвращаются только общие адресные книги. Чтобы определить, какая из адресных книг общая, а какая личная, в классе [Notes]Database предусмотрены свойства PublicAddressBook и PrivateAddressBook. Исходно все базы в массиве или векторе, полученном свойством AddressBooks, закрыты, и для них доступны только свойства FileName, FilePath, IsOpen, IsPublicAddressBook, IsPrivateAddressBook, Parent и Server. Для доступа к остальным свойствам и методам базы ее необходимо предварительно открыть методом open. Пример 1. Скрипт выводит типы и заголовки всех возвращаемых свойством AddressBooks адресных книг. При выполнении на станции будут перечислены все те адресные книги, которые вы можете выбрать в окне Select Addresses, когда выбираете получателя созданного вами почтового сообщения. Dim session As Mew NotesSession Dim books As Variant books = session.AddressBooks Forall b In books If b.IsPublicAddressBook Then t="Public NAB: " If b.IsPrivateAddressBook Then t="Private NAB: " Call b.0pen( "", "" ) Msgbox( t + b.Title ) End Forall Пример 2. Java-агент выводит имена файлов, названия серверов и заголовки всех возвращаемых свойством AddressBooks адресных книг. import, j ava . ut il . * ; © InterTrust Co. Ten. (095) 9567928 Lotus Domino R. 5: (а)-формулы, LotusScript, встроенные классы LotusScript и Java 383 // Java-Session/AddressBooks Database db; Vector books = session.getAddressBooks(); Enumeration e = books.elements( ) ; whale (e . hasMoreEierhents () ) { db ---- (Database)e.nextElement(); String fn = db.get FileName(); String server; if (db.getServer() != null) server - db.getServer(); else server ~ "Local"; if (fn !- null) db.open(); String title = db.getTitle (); System.out .println (server + " " -f fn + " \"" t- title + "\""); i Свойство AgentContext - «контекст агента»» Java: AgeniContext agentContext = Session.getAgentConte\t() Если свойство вызывается из агента, оно возвращает объект класса AgentContext. Если же свойство вызывается не из агента, возвращается null. Свойства объекта класса AgentContext позволяют получить то же самое, что и одноименные свойства объекта класса NotesSession (LotusScript), имеющие смысл только в контексте агентаСвойство UserName -«полное имя пользователя или сервера» LotusScript: Java: пате$ = notesSession.UserName Siring name = Session.getVser'NameO Полное имя текущего пользователя или сервера (тип String), например "CN=Nikolay N. foiitsev/O=InterTrustCorp/C=SU'!, Когда выполнение происходит на станции, возвращается имя пользователя. Для агента, выполняющегося на сервере, свойство всегда возвращает полное имя сервера. Свойство Common UserName - «общее имя пользователя или сервера» LotusScript: commonName$ = tiotesSession.CommonUserNtime Java: String commonName ~ &jvw"ow.getCommonUserName() Возвращается составляющая CN (тип String) из полного имени текущего пользователя, если выполнение происходит на станции, или сервера, если выполнение осуществляется на сервере. Например, если полное имя текущего пользователя "CN=Nikolay N. lontsev/O-InterTrustCorp/C=SU", свойство вернет "Nikolay N. lontsev". Если имя простое (неиерархическое), то составляющая CN для него совпадает с полным именем. Свойство EffectiveUserName - «имя пользователя или разработчика агента» LotusScript: name$ -•'-= nolesSession.'Effective'UserNume Java: String name = lSV5.y/ow.getAgentContext().getEffectiveUserName() Если выполнение происходит на станции, возвращается полное имя пользователя (тип String). Если выполнение осуществляется на сервере, возвращается полное имя владельца агента - разработчика, который создал или последним редактировал этого агента. © InterTrust Со. Тел. (095) 9567928 Встроенные классы LotusScript и Java 384 Основное назначение свойства состоит в определении лица, отвечающего за результаты выполнения агента, а область применения свойства - код агента. Поэтому в Java свойство является членом класса AgentContext, а не Session. Пример. В первом диалоговом окне может быть возвращено CN-Nikolay N. lontsev/O=InterTrustCorp/C=SU, во втором - Nikolay N. lontsev, а в третьем, когда скрипт выполняется на станции, то же, что и в первом. Dim session As New NotesSession , Messagebox session.UserName,,"session.UserName" Messagebox session. ConuaonUserName, , "session. CorninonUserName" Messagebox session.EffectiveUserName,, ''session.EffectiveOserName" 0 Свойство UserNameList - «список всех имен пользователя» LotusScript: Java: note sNanie Array - m7tes>Sbvv/o«.UserNameList java.util. Vector names - 5'e,ss/o/7.getUserNameList{) Возвращаются «массив» всех имен пользователя или сервера (в LotusScript как массив, в Java - как объект класса java.util,Vector), Элементы «массива» являются объектами класса [Notes'JName. Первый элемент «массива» соответствует основному имени, остальные -альтернативным именам пользователя (если они имеются). Пример. Скрипт выводит составляющую CN и код языка для всех имен текущего пользователя. Результат выполнения скрипта на станции может вы глядеть следующим образом: Common name is Nikolay N. iontsev Language is (основное имя) Common name is Николай Н. Ионцев Language is ru (первое альтернативное имя) Dim session As New NotesSession Dim nameslist As variant nameslist = session.UserNameList Forall nnanie in nameslist print ("Common name is " & nname.common) print ("Language is " & nname.Language) end Forall Свойство UserNameObject - «имя пользователя как объект класса Name» .. Java: Name name = ,Ses;«o?7.getUserNameObject() Возвращает основное имя пользователя или сервера как объект класса Name. Пример. Выполняясь на станции, этот Java-агент может вывести следующие строки: User name = CN-Nikolay N. Iontsev/O~-=InterTrustCorp/C=SU Common user name = Nikolay N. lontsev Effective user name = CN=Nikolay N. lontsev/O=InterTrustCorp/C~SU no.getCommonO ~: Nikolay N. iontsev Common name is Nikolay N. lontsev Language is (основное имя) Common name is Николай Н. Ионцев Language is ru (альтернативное имя) import j ava.util.*; // Java-Session/Names String un = session.getUserName(); System.out.println("User name = " + un) ; © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 385 String en = session.getCommonUserName(); System.out.println("Common user name = " + en); String en = session.getAgentContext().getEffectiveUserName(); System.out.println("Effective user name = " + en); Name no = session.getUserNameObject{); System.out.println("no.getCommon() = " + no.getCommon()); Vector nl = session.getUserNameList(); Enumeration e = nl. elements () ; -, •.: . ;: -_.,. , - • , . . . - while (e.hasMoreElements ()) { Name nobj = (Name)e.nextElement(); System.out.println (" Common name is " + nobj.getCommon()); System.out.println (" Language is " + nobj.getLanguage()); } Свойство Platform - «платформа» LotusScript: platform$ = notesSession.Platform Java: String platform = Session.gGtPlatfarmQ Платформа, на которой происходит выполнение. Возможные значения: "Macintosh", "MS-DOS", "Netware", "OS/2vl", "OS/2v2" - версии 16 bit и 32 bit, "Windows/16", "Windows/32", "UNIX" - UNIX (Sun, SCO, HPUX, A1X). Свойство Notes Version - «версия Notes» LotusScript: version$ = notesSession.NotesVersion Java: String version = getNotesVersionQ Версия Notes (тип String). Например, "Release 5.0(IntI)|30 March 1999". © Свойство NotesBuildVersion - «номер реализации Notes» LotusScript: long = notesSession.NotesJZmld Version Номер реализации Notes (тип Long). Например, 166. Пример. Скрипт выводит название платформы и название и номер реализации версии Notes.. Dim session As New NotesSession Print "Platform = "; session.Platform Print "NotesVersion = "; session.NotesVersion Print "NotesBuildVersion = "; session.NotesBuildVersion Свойство International - «характеристики среды выполнения» LotusScript: Java: Set noteslnternational = notesSession.lnternational International intl = 5ess/o«.getlnternational() Возвращает объект класса [Notes]International, представляющий характеристики среды выполнения. Свойство IsOnServer - «выполнение на сервере» LotusScript: Java: flag = notesSession.isOnServer boolean flag = tVe55/on.isOnServer() . -• Возвращает true, если выполнение происходит на сервере, или false, если на станции. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 386 v «,i,- @ Свойство ServerName - «имя сервера» ;-•-•-:-..-• '..'•*•'•'•' '•'/ " Java: "" ''•'• '' String serverName = •Sess/o/j.getServerNameQ . • .-- .-•• /:.-•- .- Возвращает полное имя сервера, на котором открыта сессия и происходит выполнение, или null, если выполнение происходит не на сервере. © Свойство ConvertMime - «преобразование TYPE_MIME_PART в Notes Rich Text» ... ... . •;.. . •••••'..., ;: • ..' .. • ' . : . - . . . .... ; : '.. ...;... ; .• .. .. ',, . . .. LotusScript: flag = noiesSession.ConveriMime notesSession.ConveriMtme-flag Java: boolean flag = Skss/cw.isConvertMime() void Session.setCon\eriMime(boolean flag) Если значение свойства равно true, то в полях типа Rich Text информация формата TYPE _M1ME_PART должна преобразовываться в формат Notes Rich Text (CD Records), если false - не должна. По умолчанию свойство равно false. Свойство CurrentDatabase - «текущая база» LotusScript: Set notesDatabase = notoSkvs/'ow.CurrentDatabase Java: Database database = 5k«'zow.getAgentContext().getCurrentDatabase() Объект класса [NotesJDatabase, представляющий базу, в которой находится данный скрипт или агент. База может оказаться как открытой, так и нет. Свойство CurrentAgent - «текущий агент» '•'•.'-'•'••'"•-. •--^•: ; -'*': LotusScript: Set notes-Agent = nolesSession.CurrentAgent Java: Agent agent — iS'ei'5/o/7.getAgeiitCoiitext().getCurrentAgeiit() • --.•'.-••'.•• ; Имеет смысл только в контексте агента и возвращает объект класса [NotesJAgent, представляющий выполняющегося в настоящий момент агента. т* ... Пример. Скрипт агента «узнает свое собственное имя». Dim session As New NotesSession Dim agent As NotesAgent • • • Dim aqentName As String •• •-•• Set agent = session.CurrentAgent agentName = agent. Name . . . . . . ._• . . - • . / - • • . - . . ; . • ' . ..••.< Свойство LastRun - «время предыдущего запуска» LotusScript: daleV= notesSession.L'AsfRun Java: DateTime date = 5es5;'o«,getAgentContext().getLastRun() Имеет смысл только в контексте агента. Возвращает дату и время (в LotusScript тип Variant of type DATE, в Java - объект класса DateTime), когда предыдущий раз выполнялся данный агент. Если агент никогда ранее еще не выполнялся, в LotusScript свойство возвращает 1 1/30/1899, а в Java - null. . . . .. Пример. Скрипт агента определяет, когда агент в предыдущий раз запускался. Например, если это имело место 15 августа 1999 года в 11:09:20 утра, свойство вернет 8/15/99 11:09:20 AM. © InterTrust Co, Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 387 Dim session As New NotesSession Dim runDate As Variant runDate = session.LastRun Свойство LastExitStatus -«статуе завершения при предыдущем запуске» LotusScript: code% = «otes'S'es.s/o/j.LastExitStatus Java: int code - 5b;«'cw.getAgentContext().getLastExitStatus() Имеет смысл только в контексте агента. Возвращает статус завершения (в LotusScript тип Long, в Java - int), имевший место при предыдущем выполнении этого агента. Статус равен О, если агент в предыдущий раз завершился без ошибок, и отличен от нуля, если имели место ошибки. Пример. Скрипт агента проверяет статус завершения при предыдущем запуске и выводит соответствующее сообщение в строке состояния. Dim session As New NotesSession If ( session.LastExitStatus = 0 ) Then Print ( "В прошлый раз агент завершился успешно" ) Else Print ( "В прошлый раз агент завершился с ошибкой" ) End If Свойство SavedData - «SavedData-документ агента» LotusScript: Set notesDocument = notesSession,S»vedData Java: Document document = &s,«'on.getAgentContext().getSavedData() Возвращает объект класса [NotesjDocument, представляющий документ, используемый агентом для сохранения информации, необходимой при следующем запуске данного агента. Свойство имеет смысл только для агента. Во всех иных контекстах оно возвращает Nothing/null. Документ для сохранения промежуточной информации агента - SavedData-документ -создается в базе автоматически в момент сохранения в ней этого агента его разработчиком. Исходно документ «пуст». При своем выполнении агент может получить объект класса [NotesjDocument, представляющий этот документ, и добавить в него новые поля с необходимыми значениями или изменить в нем значения полей. Этот документ, подобно обычному документу, участвует в репликациях, но он не может быть показан в виде. При повторном сохранении агента разработчиком после редактирования старый SavedData-документ агента удаляется, но вместо него создается «пустой» новый. Когда разработчик удаляет агента, удаляется и связанный с этим агентом SavedData-документ. «Визуально обнаружить» SavedData-документы в базе данных позволяет общедоступная программа NotesPeek - такие документы отображаются программой «в категории» Design ElementsYAgent Data. Благодаря наличию таких документов могут быть созданы агенты, поведение которых при очередном запуске зависит от результатов предыдущего запуска. Пример ]. Предположим, что каждый продавец имеет собственную базу на сервере. Совершая акт продажи, продавец создает в этой базе документ - ведомость продажи. Каждая ведомость имеет автоматически генерируемый порядковый номер. В конце каждой недели ведомости за прошедшую неделю переписываются в общий архив и удаляются из базы продавца. На следующей неделе продавец опять заполняет ведомости продаж, но нумерация их начинается с единицы. Этот агент запускается в конце недели, например, в воскресенье, и сравнивает максимальный номер ведомости, созданной продавцом на текущей неделе, с максимальным номером ведомости, созданной этим же продавцом на прошлой неделе. Агент проверяет вид, содержащий документы, © InterTrust Со. Тел. (095) 9567928 388 Встроенные классы LotusScript u Java заполненные продавцом за текущую неделю. Первый, отсортированный по убыванию, столбец в этом виде содержит номер последней созданной продавцом ведомости. Поле NumLeads этой ведомости дает количество продаж за текущую неделю. Эта величина сравнивается с количеством продаж продавца за предыдущую неделю - оно извлекается из поля MaxLeads в SavedData-документе данного агента. Результат сравнения заносится в поле Summary последней созданной продавцом на текущей неделе ведомости. В конце работы агента значение поля MaxLeads в SavedData-документе обновляется. Само «архивирование» документов за текущую неделю в тексте агента для простоты не приведено. Sub Initialize - • ' Dim session As New NotesSession Dim db As NotesDatabase Dim view As NotesView Dim doc, agentDoc As NotesDocument Dim d As Integer Set db = session.CurrentDatabase Set. view = db.GetViewf "Ведомости за текущую неделю" ) ' Первый документ в виде имеет наибольший номер Set doc = view.GetFirstDocument Set agentDoc = session.SavedData ' При первом запуске агента его SavedData-документ ' не содержит поля MaxLeads - принимаем его равным О If Not{ agentDoc.Hasltem( "MaxLeads" } ) Then agentDoc.MaxLeads = 0 Call agentDoc.Save( True, True ) End If d -" doc. NumLeads ( 0 ) - agentDoc, MaxLeads ( 0 ) If ( d > 0 ) Then doc.Summary = Abs( d ) & " больше, чем на прошлой неделе." Elseif ( d < 0 ) Then doc. Summary =-= Abs ( d ) & " меньше, чем на прошлой неделе." Else doc. Summary = "Столько же, как и на. прошлой неделе." End If ' сохранение макс, номера ведомости за текущую неделю 'в SavedData-документе agentDoc.MaxLeads = doc.NumLeads , . Call doc.Save( True, True ) Call agentDoc.Save( True, True } End Sub Пример 2. Java-агент использует SavedData-документ для вычисления «рекордной» суммы продаж за неделю. Каждый документ содержит поля Weeky_ Sales (сумма продаж за неделю) и Name (имя продавца). Все такие документы содержатся в виде Weeky Sales. SavedData-документ агента имеет поля MaxSales («рекордная» сумма продаж) и MaxSalesPerson (имя продавца-рекордсмена). Агент заменяет значение полей MaxSales и MaxSalesPerson в SavedData-документе, если значение Weeky Sales из документа превышает текущее значение MaxSales. import j ava.ut il.Vector; import java.lang.Float; .// Java-Session/SavedData Document agentDoc = agentContext.getSavedData(); Database db = agentContext.getCurrentDatabase( ) ; if (!agentDoc.hasltem("MaxSales")) { agentDoc.replaceltemValue("MaxSales", "0"); agentDoc.save(true, true); agentDoc = agentContext.getSavedData(); } View view = db.getView("Weeky Sales"); Document doc = view.getFirstDocument(); . ... © InterTrust Co. Тел. (095) 9567928 • Lotus Domino R. 5: @-форму.чы, LotusScript, встроенные классы LotusScript и Java 389 while (doc ! =•- null) • -{ Vector mvalue = agent Doc.get ItemValue("MaxSales") ; Vector wvalue = doc.getltemValue("Weekly_Sales"); Float maxSales = new Float((String) mvalue.firstElement()); Float weeklySales = new Float((String) wvalue.firstElement()); if (weeklySales.floatValue() > maxSales.floatValue()) { agentDoc.replaceltemValue("MaxSales", doc.getltemValue("Weekly_Sales")); agentDoc.replaceltemValue("MaxSalesPerson", doc.getltemValue("Name")); / } • •' • doc.replaceltemValue("Weekly_Sales", "0") ; doc.save(true, true); doc = view.getNextDocument(doc); } . • : agentDoc.save(true, true); System.out.println("Best Sales person up-to-date is " + agentDoc.getltemValue("MaxSalesPerson") + " and sold $" + agentDoc.getltemValue("MaxSales")); Свойство DocumentContext - «In-inemory-документ агента» LotusScript: Set notesDocument — «ofes5'ess/on.DocumentContext Java: Document document = &si7O77.getAgentContext().getDocumentContext() Возвращает объект класса [Notes]Document, представляющий так называемый «in-memory-документ» для данного агента. Свойство имеет смысл только для агента. Во всех иных контекстах, а так же при отсутствии in-memory-документа для агента, оно возвращает Nothing/null. При работе с таким документом в агенте нельзя пользоваться методами encrypt и remove, а также методом compact для объекта [NotesJDatabase, полученного «от этого документа» свойством Parent. Принципиально дело обстоит так, что серверная или иная внешняя программа, пользуясь средствами Notes API, может создать в виртуальной памяти документ (in-memory-документ), «ввести» этот документ в контекст агента (вызовом функции AgentSetDocumentContext из Notes API), а затем запустить агента. Этот агент во время своего выполнения, воспользовавшись свойством DocumentContext, получит доступ к данному in-memory-докумешу и затем к содержащейся в нем информации. Практически же наиболее часто встречаются два рассматриваемых ниже случая, в которых in-memory-документ для агента создается программным обеспечением станции или сервера «автоматически». Во-первых, для агента, запускаемого пользователем станции, «сама станция» автоматически создает in-memory-документ, представляющий текущий документ в интерфейсе пользователя. Во-вторых, значительно более важное применение этого механизма - получение значений CGI-переменных в агентах, запускаемых на сервере Domino из Web-броузера. Это относится к ак к аге н та м, за п уск ае м ы м и з бро уз ер а «в р уч н ую п о ко ма нде » @Command([ToolsRunMacro]) или по URL с операцией ?OpenAgent, так и к агентам, запускаемым по событиям WebQueryOpen и WebQuerySave. Перед запуском такого агента Domino Web Server (серверная задача HTTP) автоматически создает для агента in-memory-документ, содержащий поля, имена которых совпадают с именами CGI-переменных, а значения равны значениям этих CGI-переменных. Поэтому агент, получив in-memory-документ свойством DocumentContext, может «добраться до» значений CGI-переменных. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 390 Список полей, генерируемых задачей HTTP и соответствующих CGl-переменным, дается в таблице ниже. Auth Type Тип идентификации пользователя, осуществленный сервером, например: Basic Content, Length Количество байт данных в запросе. Используется при получении и обработке запроса от броузера. Эта и следующая переменные имеются только для тех видов запросов, которые поддерживают присоединенные к запросу данные, например, запрос POST Content JType Тип данных MIME для присоединенных к запросу POST или PUT данных Gateway_Interface Версия спецификации CG1, например: CG3/1.1 HTTP Accept Типы данных MIME, которые принимает клиент, как указано в заголовках HTTP HTTP__Referer URL страницы, с которой пользователь «пришел сюда» HTTPS Показывает, включена ли поддержка SSL на сервере HTTP__User_Agent . Броузер, который используется клиентом, например: Mozilla/4.0 (compatible; MSIE 4.0 1 ; Windows NT) Pathjnfo Путь, указанный пользователем в URL, например: ' ; ;: :r "" /Education/JavaLSExs.nsf/Java-Session-Web2 Path Translated «Оттранслированный» сервером путь Path Info Query _String Запрос к агенту (CGI-скрипту). Запрос представляет собой . текстовую строку, содержащую параметры запроса -соответствующую часть после символа «?» из URL запроса Remote_Addr IP-адрес хоста, с которого пришел запрос : Remote_Host Имя хоста, с которого пришел запрос, например: niontsey.inttrust.ru Remote_ldent Идентификатор пользователя, от которого пришел запрос Remote User Имя пользователя, производящего запрос, например: ' "' CN=Nikolay N. Iontsev/O=InterTrustCorp/C=SU Request ^Method Метод запроса к CGI-скрипту: GET, HEAD, POST и т.п. Request_Content Данные, передаваемые методом POST Server_Name Имя сервера, на котором выполняется CGI-скрипт, или его IP-адрес Server _Protoco! Информация о протоколе, который броузер использует для ' связи с сервером, например: НТТР/1 .1 Server Port Номер порта, через который броузер связывается с сервером Server_Sofrware Информация о программной реализации сервера, например: Lotus-Domino/Release Пример I. Агент на LotusScript получает значение из полей Form и Subject текущего документа в и нтерфейсе пользователя. © InterTrust Co. Тед. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Dim doc As NotesDocument Set doc = session.DocumentContext If doc Is Nothing Then Messagebox "Doc Is Nothing!" Else Messagebox "Form = " + doc.Form( 0 ) If 391 + " Subject = " + doc.Subject ( 0 ) End Пример 2. Java-агент получает значение из поля Subject текущего документа в интерфейсе пользователя. import Java.utii.Vector; // Java-Session/DocumentContext Document doc = agentContext.getDocumentContext(); if (doc != null) { Vector v = doc . get.ItemValue ( "Subject " ) ; System.out.println("Value of 'Subject' in document } else System, out . println ( "No document, context"); is "+v.toString (}); Пример З. Агент на LotusScript, выполняемый по событию WebQuerySave, выдает в броузер подтверждающее сообщение при сохранении документа. Для работы с CGl-переменной в документе должно присутствовать поле Remote User типа Text/Computed for display с формулой RemoteJJser. Dim session As New NotesSession Dim doc As NotesDocument Set doc = session.DocumentContext . Dim remote As Variant remote = doc . Remote___User (0 ) . Print "Документ был успешно сохранен<ВК>" Print "<Ь2>Спасибо за участие в нашем форуме, • • • . . " + remot:e+"</h2>" Пример 4. Агент на LotusScript со свойством Run Agent as Web user выводит «в броузер» значения всех доступных во время его выполнения CGI-переменмых. Dim session As New NotesSession • Set doc = session.DocumentContext Prin t " < b xf o nt s ize = 5 > D is p la y c o n te x t v aria b le s </f o n tx b x br >" Forall item In doc.items Print "<brxb>" & item. Name & ":</b>" If Isempty(item.Text) Then Print "EMPTY" Else Print item. Text. End If End Forall '. Пример 5. Java-агент со свойством Run Agent as Web user выводит «в броузер» значения всех доступных во время его выполнения CGI-переменных. import Java.uti1.*; import. Java.io.*; /'/ Java-Session-Web2 Document doc = agentContext.getDocumentContext(); PrintWriter pw = this.getAgentOutput(); if (doc == null) pw.println("No context document"); :: else . • ; - ,. { Java.util.Vector v = doc.getltems(); pw.println("Found vector with " + v.sizef) + " elements<BR>"); int i; for (i = 0; i < v.size(); i++) © InterTrust Co. Тел, (095) 9567928 Встроенные классы LotusScript и Java -> 392 { . Item item = (Item)v.elementAt(i); pw.print("Item " + i r ": ") ; if (item == null) pw.print("NULL"); else pw.print(item.getName() + " / " + item.getText(}); pw.println("<BR>"); } } 3.3.2. Методы для работы с файлом NOTES.INI Метод getEnvironmentString - «значение из NOTES.INI как строка» LotusScript: value = ?iotesSession.getEnvironment$trmg( nameS [, system ] ) Java: String value = Session.getEnvironmentString(Strmg name) String value = Session.getILn\ironmentString(Slring name, boolean system) Позволяет получить значение переменной из файла NOTES.INS. Если выполнение осуществляется па станции, значение извлекается из файла NOTES.INI станции, если на сервере - из файла NOTES.INI сервера. Параметр пате (тип String) задает имя переменной, значение которой должно быть получено. Параметр system не обязателен. Если задано true, метод использует в точности заданное первым параметром имя переменной. Если задано false, метод добавляет символ "$" в начало строки пате$ перед получением значения из файла NOTES.INI. Если параметр system опущен, он считается равным false. Возвращаемое значение value (типа Variant в LotusScript или String в Java) содержит значение этой переменной, «извлеченное» из файла NOTES.INJ. Пример 1. Скрипт получает значение переменной SIEVersionMajor из файла MOTES.INI. Например, переменная lEVerMajor получит значение "4", если в файле NOTES.INI пользователя имеется строка "$IEVersionMajor=~4". Dim session As New NotesSession Dim lEVerMajor As String " lEVerMajor = session.getEnvironmentStrxng( "lEVersionMajor" ) Msgbox lEVerMajor Пример 2. Агент получает значение переменной MailServer из файла NOTES.INI. Если в файле NOTES.INI имеется строка "MaiiServer=CN=NotesSrv400/O:r4nteiTrustCorp/C=SU", агент выведет текст MailServer is CN=NotesSrv400/O-InterTrtistCorp/C=SU. // Java-Session/getEnvironmentString String ms — session.getEnvironmentString("MailServer", true); if (ms == null) System.out.println("No MailServer"); else System.out.println("MailServer is " + ms); Метод getEnvironmentValue-«значение из NOTES.INI как число» . . . . . . LotusScript: value - notesikw/oM.getEnvironmentValuet nameS [, system ]) Java: Object value -- Session.getEnvmmme:ntValtte(String name) .. . Object value - &?^/oH.getEnvironmentValue(5ltri'nЈr name, boolean system) © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (агформулы, LotusScript, встроенные классы LotusScript и Java 393 Аналогичен методу getEnvironmentString, но используется для переменных среды, значения которых по смыслу являются числами, Возвращается значение типа Variant в LotusScript или класса Object в Java. Пример 1. Если в NOTES.INI присутствуют строки "$ENVNum=75" и "TimeZone=5", при выполнении скрипта переменная latestNumber получит значение 75, а переменная zoneNumber -значение 5. Dim session As New NotesSession " Dim latestNumber As Integer latestNumber = session.getEnvironmentValue( "ENVNum" ) Dim zoneNumber As Integer zoneNumber = session.getEnvironmentValue( "TimeZone", True ) Пример 2. В условиях предыдущего примера аналогичные результаты получит и агент на Java. // J a v a -S e s s i o n / g e t E n v i r o n me n t V a l u e Object envnum == session.getEnvironmentValue("ENVNum", false); if (envnum == null) System.out.println("No $ENVNum"); else System, out:. println ( "$ ENVNum = " т envnum); Object tz = session.getEnvironmentValue("TimeZone", true); if ( t z == null) System.out.println("No TimeZone"}; else System.out.println("TimeZone = " + tz) ; Метод setEnvironmentVar - «занесение значения в NOTES.INI»- , ....... LotusScript: Call n0/ЈsSe.M/on.setEnvironmentVar( name$, value [, system ] ) Java: void Session,setEnvironmentVar(String name, Object value) void Session.setEnvironmentVar(String name, Object value, boolean system) Позволяет присвоить значение переменной в файле NOTES.INI. Если выполнение происходит на сервере, информация заносится в файл NOTES.INI сервера, если на станции -NOTES.INI станции. Параметр пате (тип String) задает имя переменной в файле NOTES.INI, которой должно быть присвоено новое значение. Параметр value (типа Variant в LotusScript или класса Object в Java) задает новое значение для этой переменной среды. Это значение автоматически преобразуется в строку. Если же значение не удается преобразовать в строку, метод setEnvironmentVar в LotusScript генерирует ошибку "Environment variables must be strings, dates, or integers", а в Java -возбуждает соответствующее исключение. Параметр system не обязателен. Если задано true, метод использует в точности заданное первым параметром имя переменной среды. Если задано false, метод автоматически добавляет символ "$" в начало строки пате перед занесением значения в файл NOTES.INI. Если параметр system опущен, он считается равным false. Если переменная с именем пате уже существует в файле NOTES.INI, она получает новое значение. В противном случае в файл NOTES.INI добавляется новая переменная с именем пате и ей присваивается значение. Чтобы удалить соответствующую переменной строку из файла NOTES.INI, достаточно присвоить этой переменной пустую строку (""). Пример 1. Скрипт присваивает .переменной SHomeTown значение "Moscow". После выполнения скрипта в файле NOTES.INI можно обнаружить строку "$HomeTowiv=Moscow". Dim session As New NotesSession Call session.setEnvironmentVar( "HomeTown", "Moscow" ) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 394 Пример 2. Java-агент присваивает переменной SHomeTown значение "Moscow" и заменяет значение переменной MailServer на MCN^Dommo500/t>4nterTrustCorp/C=SU". // Java-Session/setEnvironmentVaiue session,setEnvironmentVar("HomeTown", "Moscow", false); session.setEnvironmentVar("MailServer", "CN=Domxno500/O=InterTrustCorp/C=SU", true) 3.3.3. Методы для создания объектов-потомков Метод getDbDirectory - «создать объект [NotesJDbDirectory» LotusScript: Java: Set notesDbDirectory = notesSession,geiDb1i)irectory( server$ ) DbDirectory dbDir •= Session,getDbDirectory(String server) Создает новый объект класса [NotesjDbDirectory, используя при этом заданное параметром server (тип String) имя сервера, к списку баз на котором необходимо получить доступ. Если в качестве значения параметра задана пустая строка (""/null), обеспечивается доступ к списку локальных баз. При ПОРччперациях параметр должен задаваться равным null. Подробности даются в описании класса [Notes]DbDirectory. Пример I. Скрипт находит и открывает первый шаблон базы на сервере Domino/Org/RU, Dim session As New NotesSession Dim directory As NotesDbDirectory Dim db As NotesDatabase Set directory = session.getDbDirectory{ "Domino/Org/RU" Set db = directory.getFirstDatabase( TEMPLATE ) Call db.open( "", "" } -. > :' . ) Пример 2. Java-агент выводит список имен всех расположенных локально баз. /'/ Java-Session/getDbDirectory DbDirectory dir = session.getDbDirectory(""); --• String Server = dir.getName(); if (Server == null) Server = "Local"; System.out.println("Database directory list on server " + Server + "\n"}; Database db = Dir.getFirstDatabase(DbDirectory.DATABASE); while (db != null) i -. String fn = db.getFileName(); String title = db.getTitle(); System.out.println(fn.toUpperCase() + " - " + title); db — Dir.getNextDatabase() ; ' } М.етод getDatabase - «создать объект [Notes] Database» LotusScript: Java: : , • ........... Set notesDatabase ~ notesSes'sion.geiDatabase( server$, db/ileS ) Database db = Session.getDatabase(Sfring server, String dbfile) Database db = Session,getDatabase(String server, String dbfile, boolean createonfail) Создает объект класса [NotesJDatabase, используя при этом заданное параметром server (тип String) имя сервера и заданное параметром dbfile (тип String) имя файла базы, и, если это удается, открывает базу. Если в качестве значения параметра server задана пустая строка (""/null), предполагается, что база расположена локально на компьютере - сервере или станции. При ПОР-операциях параметр server должен задаваться равным null. Если в © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (^-формулы, LotusScript, встроенные классы LotusScript и Java 395 качестве значений обоих параметров server и dbfile заданы пустые строки (""/null), предполагается, что база будет открыта позже. Если указанная параметрами база существует, возвращаемый объект класса [Notes]Database будет открыт. Если же база не существует, возвращаемый объект в LotusScript будет закрыт, а в Java вообще не будет создан -возвращается null. Однако, если в Java использовать метод с параметром createonfail, равным true, то объект класса Database создается, даже если указанная база не существует или ее не удалось открыть. Сам метод getDatabase новой базы не создает - для создания новой базы необходимо нужно воспользоваться одним из методов класса [Notes]Database, Дополнительные подробности даются в описании класса [Notes]Database. Пример 1. Если база plan.nsf существует на сервере Domino/Org/RU и доступна, она будет открыта, Тогда в диалоговом окне появится название этой базы. Dim session As New NotesSession Dim db As NotesDatabase Set db = session.GetDataba.se ( "Domino/Org/RU", "plan, nsf" ) Messagebox ( db. Title ) Пример 2. Java-агент выведет название базы names.nsf, если эта база существует на сервере Domino/Org/RU и доступна. Database db = session.getDatabase("Domino/Org/RU", "names,nsf"); System.out.printin(db.getTitle ()}; Метод getlJRLDatabase - «создать объект Database для Web Navigator» Java: Database db = 5e»7o«.getURLDatabase() Создает объект класса Database, представляющий базу данных Web Navigator. Это может быть база данных WEB.NSF на сервере, «несущем» серверную задачу WEB, или «клиентская)) база Web Navigator. Метод resolve - «создать объект, имеющий заданный URL» Java: Base obj - Scssion.resolve(String url) Возвращает объект Domino классов Database, View, Form, Document или Agent, имеющий URL, заданный строкой url. Метод имеет смысл только для «удаленной (ПОР) сессии». В «локальной сессии» будет возбуждено исключение "Not implemented". Метод createRegistration - «создать объект [NotesJRegistration» LotusScript: Set notesRegistration = New NotesRegistration Java: Registration variableName — se$sion.crenteRegistration() В Java создает новый объект класса Registration. В LotusScript объект класса NotesRegistration получают методом New. Подробности даются в описании класса |NotesJRegistration. Метод createRichTextStyle - «создать объект [NotesJRichTextStyle» LotusScript: Set notesRichTextStyle = notesSession.cresiteRicliTe\iStyle( ) Java: RichTextStyle rtsObj = &5,y/o/7.createRichTextStyle() Создает новый объект класса [NotesJRichTextStyle. Объект этого класса позволяет управлять -«шрифтовым оформлением» поля типа RichText. Подробности даются в описании класса [NotesJRichTextStyle. © InterTrust Со. Тел. (095) 9567928 Встроенные классы LotusScript и Java 396 © Метод createRiehTextParagraphStyle - «создать объект [NotesJRichTextParagraphStyle» LotusScript: Set notesRichTextParagraphStyle = w0/e.SiS'eASK»7.createRichTextParagraphStyle() Java: ^~' RichTextParagraphStyle psObj =:- ,Skw70w.createRichTextParagraphStyIe() Создает новый объект класса [NotesJRichTextParagraphStyle. Объект этого класса позволяет управлять «оформлением» абзацев в поле типа RichText. Подробности даются в описании класса [NotesJRichTextParagraphStyle. Метод createNewsietter - «создать объект [NotesJNewsletter» LotusScript: Set notesNewsletter = notesSession.createNewsletter( notesDocumentCoUection ) Java: Newsletter nl = Ses'sion,crea.teNewsletter(DocumentCoIfection collection) Создает новый объект класса [NotesJNewsletter, содержащий заданную в качестве параметра коллекцию документов (объект класса [NotesjDocumentCoilection), Подробности даются в описании класса [NotesJNewsletter. Метод createLog - «создать объект [NotesJLog» , ••.•. LotusScript: Set notesLog ~ notesSession.ereateLog( name$ ) Java: Log log - Session.createLiOg(String name) Создает новый протокол - объект класса [NotesJLog с именем, заданным параметром пате (тип String). Подробности даются в описании класса [NotesJLog. Пример I. Скрипт создает протокол с именем "Checkup Agent". Dim session As New NotesSession Dim log As NotesLog Set log = session. createLog ( "Checkup Agent," ) Call log.openMailLog ( "Nikolay N. lontsev", "Log for Checkup Agent" ) Call log.close Пример 2. Java-агент создает протокол с именем ''Checkup Agent". // Java-Sess.ion/createLog Log log — session.createLog("Checkup Agent"); log.openMailLog("Nikolay N. lontsev", "Log for checkup agent"); log.close(}; © Метод createName - «создать объект [NotesJName» LotusScript: Set notesName ~ notesSession.crcuteName( nameS ) Java: Name nameObj -= Session.cre'AteName(String name) • • •. . . . .. , Name nameObj = Session,createName(String name, String Jang) Создает новый объект класса [NotesJName, используя при этом заданное строкой пате имя пользователя или сервера. Строка long задает язык, ассоциированный с именем пользователя. Подробности даются в описании класса [NotesJName. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 398 3.3.4. Прочие методы Метод updateProcessedDoc - «отметка документа об обработке агентом» LotusScript: Java: Call notesSession.apdateProcess&dDuc( notesDocument) . vo/^.9eM/o«.getAgentContext().update.ProcessedDoc(Z)0CMmew/ doc) Отмечает документ, заданный параметром метода, как «обработанный этим агентом». Метод используется лишь в агентах, которые обрабатывают только созданные или модифицированные после времени предыдущего выполнения данного агента документы. Во всех иных случаях данный метод не выполняет никакого действия. В агенте, обрабатывающем только созданные или модифицированные после времени предыдущего выполнения данного агента документы, для отбора таких документов должны использоваться свойство UnprocessedDocuments или методы unprocessedFTSearch или unprocessedSearch. Эти свойство и методы аналогичны в LotusScript и Java, но в LotusScript они являются членами класса NotesDatabase, тогда как в Java - членами класса AgentContext. Все они рассматриваются в 3.5. Однако для того, чтобы эти свойство и методы могли находить еще необработанные данным агентом документы, после завершения обработки каждого документа агент «должен отметить документ как обработанный», вызвав метод updateProcessedDoc. Если же агент не вызывает метод updateProcessedDoc для отметки документов как уже обработанных, свойство UnprocessedDocuments будет возвращать коллекцию всех документов из базы, а методы unprocessedFTSearch и unprocessedSearch будут возвращать все удовлетворяющие заданному критерию отбора документы, не учитывая при этом, что некоторые из этих документов уже были обработаны при предыдущем запуске агента. Для каждого из агентов, использующих метод updateProcessedDoc, в документе создается уникальная отметка об обработке агентом. Иными словами, если агент А отмечает документ как обработанный, то для агента В эта отметка (что документ был обработан агентом А) не доступна, а потому не имеет никакого значения. Для агента В доступна и имеет значение только отметка об обработке этого документа агентом В. Пример 1. Агент на LotusScript при очередном запуске обрабатывает только те документы, которые были созданы или модифицированы после предыдущего запуска этого агента. Свойство UnprocessedDocuments возвращает коллекцию таких документов. Коллекция просматривается агентом в цикле. Каждый документ из коллекции методом updateProcessedDoc отмечается как «уже обработанный агентом». Собственно сама обработка документа в этом примере не приведена, поскольку требует привлечения ещё не рассмотренных нами методов классов NotesDocument и Notesltem. Sub Initialize Dim session As New NotesSession Dim db As NotesDatabase Dim collection As NotesDocumentCollection Dim doc As NotesDocument Set db = session.curreritDataba.se Set. collection = db. UnprocessedDocuments For j = 1 To collection. Count-Set doc = collection. getNtliDocument ( j ) Call session.updateProcessedDoc( doc ) Next-En d Sub ; Пример 2. Java-агент реализует те же действия, что и агент на LotusScript из предыдущего примера. // Java-Session/updateProcessedDoc Document-Collection collection ~ agentContext. getUnprocessedDocuments () ; © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: ®-формулы, LotusScript, встроенные классы LotusScript и Java 399 Document doc; int size = collection.getCount(); for (int i = 1; i <= size; i++) { . doc = collection.getNthDocument{i); agentContext.updateProcessedDoc(doc); } ; -. • ' Метод evaluate- «вычислить @-формулу» LotusScript: evaluate (formula$ [ , notesDocument ] ) Variant = evaluate (formulas [, notesDocument ] ) Java: java.util. Vector v = session.e\'alunte(String formula) java.util. Vector v = aession.evaluate(Slring formula, Document doc) Метод имеется только в Java - в LotusScript аналогичное действие выполняется оператором или функцией Evaluate самого языка. Метод выполняет @-формулу Notes, заданную строкой formula. Если формула имеет смысл только «в контексте документа» (например, она использует информацию из полей документа, определяет дату создания или модификации документа и пр.), следует использовать метод с двумя параметрами, где doc является объектом класса Document, представляющим необходимый документ. Возвращаемое значение является объектом класса java.util.Vector, содержащим результат вычисления формулы. В случае, если формула возвращает скалярное значение, результат содержится в первом элементе объекта java.util. Vector. @-формула не должна «предпринимать попыток» изменить обрабатываемый ею документ - допустимо только извлечение информации из документа. @~функции, выполнение которых возможно только в интерфейсе пользователя (@Command, @DbManager, @DbName, @DbTitle, @DDEExecute, @DDEInitiate, @DDEPoke, @DDETerminate, @DialogBox, @PickList, @PostedCommand, @Prompt и @ViewTitle) не выполняются методом evaluate. Пример. В документах имеется поле Amount, которое может содержать список числовых значений. Java-агент выводит для каждого документа сумму всех элементов из его поля Amount. import j ava.ut i1.*; // Java-Session/evaluate Database db = agentContext.getCurrentDatabase(); DocuinentCollection dc = db. getAHDocuments () ; Document doc; System, out .println ( "Count - " + dc.getCount ()); for (int j = 0; j < dc.getCount{); j++) { doc ~ dc.getNthDocument(j); Vector v = session.evaluate("@Sum(Amount)", doc); System.out.println(v.firstElement()+" 'M-doc.getltemValue("Subject")); } Метод freeTimeSearch - «поиск отрезка свободного времени» LotusScript: Set notesDateRange = notesSession.freeTimeSe%rch( window, duration, names [, firstfit]) Java: /ava. utiL Vector dr Session.fi"eeTimeSea,rch(DateRange window, int duration, Object names, boolean firstfit) ©InterTrustCo. Тел. (095) 9567928 400 ' Встроенные классы LotusScript и Java Выполняет поиск отрезка свободного времени заданной продолжительности для указанных пользователей в заданном «окне поиска». Параметр window (объект класса [Notes] Date Range) задает отрезок времени, на котором выполняется поиск отрезков свободного времени необходимой продолжительности duration (тип Integer/int) минут для пользователей или групп, чьи имена заданы параметром names (в LotusScript строка или массив строк, в Java - объект класса String или объект класса java.util.Vector с элементами класса String). Возвращается «массив» возможных отрезков свободного времени (в LotusScript массив объектов класса NotesDateRange, в Java - java.util.Vector с элементами класса DateRange). Если найти отрезок свободного времени не представляется возможным, в Java будет возвращен null, а в LotusScript - массив, первый элемент которого является «пустым объектом» (Nothing). Если параметр firstfit равен true, метод возвращает «в массиве» только первый возможный отрезок свободного времени, если false (в LotusScript это значение по умолчанию) - все возможные отрезки свободного времени. Пример. Скрипт выполняет поиск «в окне» продолжительности в одни сутки 60-минутного отрезка свободного времени для возможной встречи трех пользователей. Когда последний параметр метода задан равным False, результат может быть следующим: 1: 2: 3: 4: 5: [09.03.99 [09.03.99 [10.03.99 [10.03.99 [10.03.99 10:00:00 13:00:00 09:00:00 13:00:00 16:00:00 ZE3, ZE3, ZE3, ZE3, ZE3, 09.03.99 09.03.99 10.03.99 10.03.99 10.03.99 12:00:00 17:00:00 12:00:00 15:00:00 17:00:00 ZE3] ZE3] ZE3] ZE3] ZE3] Если в тех же условиях последний параметр метода выбран равным True, то из предыдущего останется только первый вариант. Dim session As New NotesSession Dim window As NotesDateRange Set window i: session. CreateDateRange () Dim startDateTime As New NotesDateTime("Today") Set. window. StartDateTime = startDateTime Dim endDateTime As New NotesDateTime("Tomorrow") Set window.EndDateTime = endDateTime Dire names(1 To 3} As String names(1) = "Andre A. Linev/InterTrustCorp/Su" names(2) = "Nikolay N. lontsev/InterTrustCorp/SU" names(3) = "Vladimir A. Panov/InterTrustCorp/SU" Dim freeTime As Variant freeTime = session.FreeTimeSearch(window, 60, names, False) If (freeTime(0) Is Nothing) Then Messagebox "Нет свободного времени" Else i-1 Dim b As New NotesDateTime("") Dim e As New NotesDateTime("") E'orall x In freeTime Set b = x.StartDateTime Set e = x.EndDateTime Messagebox Str(i) & " [" & b.LocalTime & ", " & e.LocalTime & "]" i = i+1 End Forali End If " © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (а^-формулы, LotusScript, встроенные классы LotusScript и Java 401 3.4. «Множество баз» - класс [Notes] DbDirectory Представляет множество баз данных на сервере Domino или станции Notes. Это базы данных, находящихся в каталоге данных, рекурсивно в его подкаталогах, всех доступных Directory Link's и рекурсивно их подкаталогах. Directory Link - текстовый файл с расширением .DIR в каталоге данных или его подкаталоге, который содержит в первой строке полное название каталога с базами, иного, чем каталог данных, а в остальных строках может содержать список пользователей и групп, имеющих доступ к базам в этом каталоге. Такая возможность удобна в случае, когда диск, на котором находится каталог данных сервера, «переполнен», но имеется другой свободный диск, или когда просто необходимо разграничить доступ пользователей сразу к целым семействам баз. Методы [NotesJDbDirectory позволяют «просматривать в цикле» представленное объектом множество баз и получать из него любую нужную базу - объект класса [NotesJDatabase. Кроме того, в классе DbDirectory (Java) имеются методы для создания новых и «открытия» существующих баз. Аналоги этих методов для LotusScript «располагаются» в классе NotesDatabase. «Контейнерная иерархия» Как в LotusScript, так и в Java для получения объекта класса [NotesJDbDirectory обычно используется метод getDbDirectory класса [NotesJSession. LotusScript: Set notesDbDirectory = «0/esYSew/ow.getDbDirectory( serverNameS ) Java: DbDireclory DbDir = Session.gefDbDirectory(String serverName) Кроме того, в LotusScript для создания объекта класса NotesDbDirectory можно использовать метод New. Dim variableName as New NotesDbDirectory( serverName$ ) или Set notesDbDirectory — New NotesDbDirectory( serverNameS ) Параметр serverName (тип String) задает имя сервера, к множеству баз на котором необходимо получить доступ. Пустая строка (""/null) обозначает множество баз на локальном компьютере. Однако при ТЮР-обращениях параметр serverName должен задаваться равным null. Пример. Скрипт получает доступ к множеству баз на сервере NotesSrv400/InterTrustCorp/SU, находит там первый шаблон базы и открывает его. Dim directory Аз NotesDbDirectory Dim db As NotesDatabase Set directory = New NotesDbDirectory( "NotesSrv400/InterTrustCorp/SU" ) Set db = directory.GetFirstDatabase( TEMPLATE ) Call db.Open( " " , " " ) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 402 3.4.1. Свойства @ Свойство Parent-«родитель» Java: Session session = Z)/?/)/reetory.getParent() Возвращает «своего родителя» - объект класса Session, содержащий данный объект класса DbDirectory. Свойство Name - «имя сервера» . LotusScript: serverNameS ~ notesDbDirectory.Name Java: String serverName - DbDirectory.geiNameQ ••••••- . . . • • . •••.•. . Возвращает имя сервера (тип String), на котором находится множество баз, представляемое объектом - т.е. то значение, которое было задано при создании объекта методом New или getDbDirectory. Если объект представляет множество баз на локальном компьютере, возвращается пустая строка. 3.4.2. Методы для навигации по множеству баз Метод getFirstDatabase - «первая база из множества» .......... ' ' LotusScript: Set notesDatabase - wofesD6.D/rectory.getFirstDatabase( dbType% ) Java: Database db = DbDirectory.geiFir$tDutabase(int dbType) .'.. : 1}озвращает объект класса [Notes]Database, представляющий первую базу указанного параметром dbType типа из множества баз, к которому применяется метод. Параметр dbType (константа типа Integer/int) может быть одним из следующих: * DATABASE/DbDirectory.DATABASE - любая база Notes (.nsf, .nsg, .nsh); * TEMPLATE/DbDirectory.TEMPLATE - любой шаблон базы "Notes (.ntf); * REPLlCA_CANDIDATE/DbDirectory.REPLICA..CAMDIDATE - любая база Notes или шаблон базы, для которых не запрещены репликации; * TEMPLATE_CANDIDATE/DbDirectory.TEMPLATE_CANDIDATE - любая база, которая может быть шаблоном. Возвращаемый объект класса [NotesjDatabase будет закрыт. В случае, если множество баз пустое, возвращается Nothing/null. Учтите, что каждый вызов метода заново выполняет относительно продолжительный процесс сканирования содержимого каталогов. Метод getNextDatabase - «следующая база .из множества». ,.:.- •;•; ••;••'• '•••'/ •:": ~ : LotusScript: Set notesDatabase - notesDbDirectory.geiNe\tDataba$e Java: Database db - /J&D/rectory.getNextDatabaseO Возвращает следующий объект класса [NotesjDatabase заданного при предшествующем вызове метода getFirstDatabase типа из множества баз, к которому применяется метод. Возвращаемый объект класса [NotesjDatabase, как и в предыдущем методе, будет закрыт. Когда все базы «уже просмотрены», возвращается Nothing/null. © InterTrust Со, Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 403 Пример 1. Скрипт выводит в окне полные имена файлов всех имеющихся на сервере баз. Dim directory As NotesDbDirectory Dim db As NotesDatabase server$ = "NotesSrv400/InterTrustCorp/SU" Set directory - New NotesDbDirectcry( server$ ) dbType% = DATABASE Set db = directory.GetFirstDatabase ( dbType% ) counter* =0 While Not ( db is Nothing } counter% = counter% + 1 Messagebox Cstr (counterl;) + " : " + db . FilePath, , server-? S et d b = dire ctor y .G etN e xtD ata base Wend •Messagebox "Обнаружено " + Cstr(counterl) + " баз",,servers Пример 2. Java-агент выводит список имен файлов, названий и времен модификации для всех имеющихся на локальном компьютере шаблонов. // Java-- DbDi г ее tor у/ get. FirstNext Database DbDirectory Dir = session . getDbDirectory (null) ; System.out.println("Local templates\n"}; Database db = Dir.getFirstDatabase(DbDirectory.TEMPLATE); while (db != null) r i System.out.println(db.getFileName()+" "+db.getTemplateName()); db.open(}; • System.out.println(" LastModifled: " t db.getLastModified().getLocalTime()); ' db = Dir.getNextDatabase(); . .. . 3.4.3. Методы для создания и «открытия» баз в Java Метод ereateDatabase - «создать новую базу» . . •-•••.-:• .-.';.-..•. •:/.-. . LotusScript: Call notesDatabase.creatc( server$, dbfileS, openFlag ) Java: Database db = DbDirectory.cre'AteDatabase(String dbfile} Database db - D^Ј>/rectory.createDatabase(5?r/ng dbfile, boolean open) Метод createDatabase создает на диске сервера или станции (смотря по тому, что представляет объект DbDirectory) файл новой базы данных с именем dbfile. Возвращается объект класса Database, представляющий созданную базу данных, или null, если ее не удалось создать. Поскольку новая база создается без выбора шаблона - по «шаблону -Blank-» она не будет содержать элементов дизайна, кроме одного «безымянного» вида. Если использован вариант метода с одним параметром или параметр open равен false, возвращаемый объект класса Database будет закрыт. Если параметр open равен true, метод дополнительно предпринимает попытку открыть базу. Метод openDatabase - «открыть базу» LotusScript: flog — notesDatabase.open( server$, dbflle$ ) Java: Database db = DbDirectory,openD&tab'Ase(String dbfile) Database db = DbDirectory.openDatabuse(String dbfile, boolean failover) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 404 Метод openDatabase открывает существующую на сервере или станции (смотря по тому, что представляет объект DbDirectory) базу данных с именем dbfile. Возвращается объект класса Database, представляющий эту базу данных, или null, если файл базы не существует или открыть его не удалось. Для открытой базы данных доступны все свойства и методы. Вариант метода с двумя параметрами ориентирован на применение в кластере. Если параметр failover равен true, и базу не удалось открыть на том сервере-члене кластера, который представлен объектом DbDirectory, предпринимается попытка открыть реплику этой базы на другом сервере-члене кластера. Если все удалось, то свойства Server и FilePath объекта Database будут содержать информацию о сервере и имени файла той реплики базы, которая была действительно открыта. Пример. Java-агент открывает локальную базу names.nsf и выводит ее название. // Java-DbDirectory/openDatabase DbDirectory Dir = session.getDbDirectory(""); Database db = Dir.openDatabase("names.nsf"); System.out.println(db.getTitle()) ; —-—--. Метод openDatabaseByReplkalD - «открыть базу по идентификатору реплики» . . ;.':/;'•'.•'":.•"' LotusScript: flag = w/es'Z>rfa/>ase.openByRep!icaID( server$ , replicaID$ ) Java: Database db = Z)^D/rectorv.openDatabaseByRepIicaID(Sr/«g replicalD) Метод openDatabaseByReplicalD открывает существующую на сервере или станции (смотря по тому, что представляет объект DbDirectory) базу данных с заданным параметром replicalD идентификатором реплики. Возвращается объект класса Database, представляющий эту базу данных, или null, если файл базы с таким идентификатором реплики не существует или открыть его не удалось. Для открытой базы данных доступны все свойства и методы. Пример. Java-агент открывает локальную базу по идентификатору реплики. // Java-DbDirectory/openDatabaseByReplicalD DbDirectory Dir= session.getDbDirectory(null); String rid = "8b2564D2000B5144"; Database db = Dir. OpenDatabaseByReplicalD(rid) ; if (db ! --- null) System.out.println("HELP was located and opened"); else System.out.println("HELP was not found"); . . . •> Метод openDatabaselfModified - «открыть базу, если была модифицирована» LotusScript: flag = notesDatabase.openlfModitied( serverS, dbfileS, notesDateTime ) Java: Database db ~ DbDirectory,openJ)atabiiselfModiued(String dbfile, Date Time date) Метод openDatabaselfModified открывает существующую на сервере или станции (смотря по тому, что представляет объект DbDirectory) базу данных с именем dbfile, если время последней модификации этой базы не ранее заданного параметром date времени (объект класса DateTime). Возвращается объект класса Database, представляющий эту базу данных, или null, если файл базы не существует, ее не удалось открыть или она не была открыта, поскольку не была модифицирована после заданного времени. Для открытой базы данных доступны все свойства и методы. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (a^f-формулы, LotusScript, встроенные классы LotusScript и Java 405 Пример. Java-агент определяет, была ли общая адресная книга модифицирована за последние 3 часа. // Java-DbDirectorу/openDatabaseIfModified DbDirectory Dir = session.getDbDirectory("Domino500/InterTrust.Corp/SU"); DateTime dt = session . createDateTirne ( "Today" } ; dt.setN.ow() ; dt. adjust.Hour (-3) ; Database db = Dir . openDatabaselffModif iecl( "names . rxsf" , dt) ; if (db != null) System.out.println("Database has been modified in the past 3 hours"); else System,out.println("Database hasn't been modified in the past 3 hours"); Метод openMailDatabase - «открыть почтовый ящик» LotusScript: Call notesDatabaae.openMail Java: Database db - D&D/m'/ory.openMailDatabaseQ Метод openMailDatabase открывает «почтовый ящик» текущего пользователя. Возвращается объект класса Database, представляющий эту базу данных, или null, если файл базы не существует или ее не удалось открыть. Метод может вызываться, во-первых, из агента или приложения, работающего на станции пользователя, во-вторых, из агента, работающего на почтовом сервере пользователя-«владельца агента», и в третьих, из приложения или апплета, выполняющего ПОР-вызовы к почтовому серверу пользователя. Если метод вызван на станции, то почтовый сервер пользователя и имя файла его почтового ящика устанавливается по информации из локального файла NOTES.INI. Если же метод вызван из агента, выполняющегося на сервере, то «владельцем агента» считается тот, кто последним модифицировал агента, а почтовый сервер и файл почтового ящика этого субъекта определяется по информации из общей адресной книги, расположенной на этом сервере. При использовании ИОР-операций текущим пользователем считается тот, кто «открыл сессию», а местоположение его почтового ящика устанавливается по информации из общей адресной книги, расположенной на этом сервере. Если оказывается, что почтовый ящик находится на друго м сервере, возбуждается исключение, поскольку сервер не может открыть базу данных на другом сервере. Пример. Java-агент выводит информацию о почтовом ящике текущего пользователя. // Java-DbDirectory/openMailDatabase DbDirectory Dir = session.getDbDirectory(null); Database db = Dir.openMailDatabase( ) ; DocumentCollection dc -- db.getAllDocuments(); System.out.println("Mail database : " + db.getTitle() + " is " + ,(db. getSize () /1024) + "KB long arid has " + dc. getCount () + " documents"); / © InterTrust Co. Тел. (095) 9567928 406 Встроенные классы LotusScript и Java 3.5. «База данных» и «контекст агента» - классы [NotesfDatabase и Agen (Context Объект этого класса представляет базу данных Notes. Свойства объекта класса [Notes]Database позволяют получать доступ к содержащимся в базе объектам: списку управления доступом (ACL), агентам, коллекции из всех документов, видам, необработанным агентами документам, а также контролировать свойства самой базы: идентификатор реплики, сервер размещения, путь и имя файла, размер базы, максимальный размер и величину неиспользуемого пространства, название базы, категории, название дизайн-шаблона (если база сама является шаблоном или наследует дизайн с другого шаблона), дату-время создания и модификации, наличие индекса полнотекстового поиска и дату-время последнего изменения этого индекса, текущий уровень доступа пользователя, список менеджеров, и, наконец, является ли база общей или личной адресной книгой и открыта ли она. Методы объекта класса [Notes]Database позволяют открывать базу несколькими способами, создавать новую базу (пустую или по нужному дизайн-шаблону), создавать новую копию или реплику базы, инициировать репликацию базы с заданным сервером, удалять базу, уплотнять базу, обновлять индекс полнотекстового поиска, выполнять запрос полнотекстового поиска или запрос с формулой отбора и получать коллекцию удовлетворяющих запросу документов (включая или не включая ранее обработанные агентом документы), находить документ по идентификатору документа или, в базе Web Navigator, по универсальному указателю ресурса, создавать в базе новый документ, получать доступ к виду по его имени, определять или изменять уровень доступа к базе любого субъекта. «Контейнерная иерархия» LotusScript NotesSession ~> NotesDatabase — > NotesACL NotesDbDirectory NotesAgent NotesU [Database NotesView New NotesForm NotesOutline NotesDocument NotesDocumentCollection NotesReplication NotesDatabase NotesSession Java 1 Session _> Database — > ACL AgentContext Agent DbDirectory View Form Outline Document Documented lection Replication DataTime Database 1 Session Для создания нового или получения доступа к существующему объекту класса [Notes']Database возможны следующие пути: • для доступа к существующей базе, если известны имена сервера и файла базы, используют метод New или метод! getDatabase класса [NotesjSession €> InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: (al-формулы, LotusScript, встроенные классы LotusScript и Java • • • • • • • • • • 407 для доступа к базе, в которой выполняется скрипт или Java-агент, не указывая явно имен сервера и файла базы, удобно использовать свойство CurrentDatabase класса NotesSession/AgentContext для доступа к существующей базе, когда известен ее идентификатор реплики, используют метод openByReplicalD класса NotesDatabase или метод openDatabaseByReplicalD класса DbDirectory для доступа к существующей базе, когда известен только «несущий» её сервер, но не известно имя файла, используют методы класса [TMotesJDbDirectory для доступа к почтовому ящику текущего пользователя используют метод openMail класса NotesDatabase или метод openMailDatabase класса DbDirectory чтобы открыть базу Web Navigator, применяют метод openURLDb класса NotesDatabase или openURLDatabase класса Session для доступа к адресным книгам рациональнее использовать свойство AddressBooks класса [Notes]Session для проверки существования базы на заданном сервере можно воспользоваться свойством IsOpen или методами open или openlfModified класса NotesDatabase или openDatabase или openDatabaselfModified класса DbDirectory для создания новой базы на основе существующей базы предназначены методы createCopy, createFromTemplate, createReplica класса [Notes]Database для создания новой пустой базы служит метод create класса NotesDatabase или метод createDatabase класса DbDirectory для доступа к базе из объектов классов [Notes] View, [Notes] Document, [Notes]DocumentCollection, [NotesjACL или [Notes]Agent используют свойство Parent или ParentDatabase. Метод New создает в виртуальной памяти новый объект класса NotesDatabase, представляющий базу данных на указанном сервере и в указанном файле (а не новую базу!), и, если это возможно, открывает эту базу. Dim variableName As New NotesDatabase( server$, dbfde$ ) или Set notesDatabase — New NotesDatabase( server$, dbflleS ) Параметр serverS (тип String) - имя сервера или пусто (""), если база находится на том же компьютере, на котором выполняется скрипт. Параметр dbfileS (тип String) задает путь и имя файла базы. Если база расположена не в каталоге данных Notes, нужно указывать полный путь. Если оба параметра dbfileS и server$ заданы пустыми, предполагается, что они будут заданы позже, при открытии базы. Возвращаемое значение notesDatabase - объект класса NotesDatabase. Если база на сервере serverS в указанном файле dbfileS существует, метод открывает объект класса NotesDatabase, и вам будут доступны все свойства и методы класса. Если же база в указанном месте не существует, объект класса NotesDatabase закрыт, и вам будут доступны лишь немногие свойства и методы класса. Все свойства и методы класса [NotesJDatabase доступны только после того, как объект [NotesJDatabase будет открыт. В большинстве случаев это происходит автоматически. Открытие объекта не произойдет лишь в следующих случаях: • • Агент выполняется на сервере и пытается открыть базу на другом сервере. Возникает ошибка или возбуждается исключение. Скрипт или Java-приложение пытаются открыть базу, к которой они не имеют необходимого уровня доступа. Возникает ошибка или возбуждается исключение. Необходимо иметь по крайней мере доступ читателя к открываемой базе. © InterTrust Co. Тел. (095) 9567928 408 Встроенные классы LotusScript и Java • Объект [NotesjDatabase, полученный из объекта ["NotesJDbDirectory, исходно закрыт. Для полученного таким способом закрытого объекта [Notes]Database доступны только его свойства Categories, Delay-Updates, DesignTemplateName, FileName, FilePath. IsOpen, Parent, ReplicalD, Server, SizeQuota, TemplateNatne, Title. Чтобы пользоваться всеми свойствами и методами, нужно явно открыть базу. • Объект [Notes] Data base, полученный свойством AddressBooks из объекта класса [Notes]Session, исходно закрыт. Для полученного таким способом объекта доступны только свойства FileName, FilePath, IsOpen, IsPrivateAddressBook, IsPublicAddressBook, Parent, Server. Чтобы пользоваться всеми свойствами и методами, нужно явно открыть базу. • Объект NotesDatabase, полученный методом New, будет закрыт, если базы нет в указанном параметрами server^ и dbfileS местоположении. Для такого объекта доступны лишь свойства FileName, FilePath, IsOpen, Parent и Server. Под уровнем доступа скрипта или Java-приложения к базе понимается возможность открыть базу и читать документы, создавать документы, модифицировать или удалить документы, изменить ACL и т.п. Под уровнем доступа агента к серверу понимается его возможность выполняться на сервере - она регламентируется в документе Server из общей адресной книги. Когда скрипт или Java-приложение выполняются на станции пользователя, их уровень доступа к базе совпадает с уровнем доступа к этой базе пользователя, под ID-файлом которого работает станция, а при «удаленных» (НОР) обращениях к серверу - совпадает с уровнем доступа к этой базе аутентифицированного сервером пользователя. Если делается попытка выполнить операцию с базой, не имея к ней необходимого уровня доступа, возникает ошибка или генерируется исключение. Если агент выполняется на сервере (например, по расписанию или событию получения почты), уровень доступа агента к серверу определяется в соответствии с правами создателя этого агента (того, кто последним модифицировал агента) в документе Server из общей адресной книги, а уровень доступа этого агента к базе совпадает с уровнем доступа создателя агента к этой базе. Агент не будет выполнен на сервере, если он не имеет необходимого доступа к серверу - соответствующее сообщение появится на консоли сервера. Если агент может выполняться на сервере, но не имеет необходимого уровня доступа к базе, в ходе его выполнения возникает ошибка или генерируется исключение. Пример 1. Скрипт создает новый объект класса NotesDatabase для доступа к базе plan.nsf на сервере Server 1/Acme/RU. Если база существует, объект будет открыт. Dim db As NotesDatabase Set db = New NotesDatabase{ "Serverl/Acme/RU", "plan.nsf" ) Messagebox( db.Title ) Пример 2. Скрипт делает то же самое, но он короче. Dim db As New NotesDatabase( Messagebox( db.Title ) "Serverl/Acme/RU", "plan.nsf" ) Пример 3. Java-агент создает новый объект класса Database для доступа к базе plan.nsf на сервере Serverl/Acme/RU. Если база существует, объект будет открыт. ,' / Java-Database/Databasel Datab ase d b = sess ion. getDa ta base("Serv e rl/A cme/RU" , System, out. print In ( db . get Т it. le () ) ; "p lan. nsf"); Пример 4. Скрипт использует свойство IsOpen для проверки, существует ли база QUACK.NSF в каталоге birds на компьютере, выполняющем скрипт. Если база не существует, скрипт создает новую методом Create. Dim db As New NotesDatabase( "", InterTrust Co. Тел. (095) 9567928 "birdsXquaak.nsf" ) © Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 409 •...-..:• If db.IsOpen Then Messagebox( "База уже существует" ) Else Messagebox( "Создание новой базы... " ) Call db.Create( "", "", True ) db.Title = "Ducks of North America" End If Пример 5. Java-агент использует свойство isOpen для проверки, существует ли база QUACK.NSF в каталоге birds на компьютере, выполняющем скрипт. Если база не существует, агент создает новую методом createFromTemplate no шаблону discswSO.ntf. /7 Java-Database/Database2 ' . - • - Database? db, template; db = session.getDatabase(null, "birds\\quack"); if (db.isOpen()) S уs t em.out.pri nt1n(db.ge t Т i11e() ) ; " . else { " ' ' System, out.. print In ( "Creating new database ..."); template = session. getDatabase (null , "disc.sw50.ntf"); if (template.isOpen()) { db = template.createFromTemplate(null, "birds\\quack", true); db. setT.it le ( "Ducks of North America"); System, out. print In (db . get-Title ()); } else System.out.println("Template discswSO.ntf does not exist"); } .<:• , , - , - , - ' .' % " - - • - - • • Пример 6. Скрипт предоставляет пользователю Brian Flokka/Acme/US доступ редактора к текущей базе. Текущая база - база, в которой находится и выполняется этот скрипт. Использование свойства CurrentDatabase класса NotesSession способствует разработке универсальных скриптов, «не привязанных» к конкретным именам баз. Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase Call db.GrantAccess( "Brian Flokka/Acme/US", ACLLEVEL EDITOR ) Пример 7. To же самое делает Java-агент. // Java-Database/DatabaseS Database db = agentContext.getCurrentDatabase{); db.grantAccess("Brian Flokka/Acme/US", ACL.LEVEL EDITOR); Пример 8. Скрипт использует метод Open для проверки существования базы salesdocs.nsf на сервере Server 1/Acme/RU. Если база существует, скрипт добавляет группу Supervisors в ее ACL. Dim db As New NotesDatabase( "", "" ) If db.Open( "Serverl/Acme/RU", "salesdocs.nsf" ) Then Call db.GrantAccess ( "Supervisors", ACL-LEVEL_EDITOR ) End If ' Пример 9. Скрипт демонстрирует методы New и OpenlfModified для открытия базы только в том случае, если она была модифицирована после указанной даты. Если база SALESDOCS.NSF на сервере Serverl/Acme/RU была модифицирована в течении суток, скрипт открывает базу и уплотняет ее. Dim db As New NotesDatabase( " " , » " ) Dim dateTime As New NotesDateTime( "Today" ) Call dateTime.AdjustDay( -I } If db.Open!fModified( "Serverl/Acme/RU",, "salesdocs.nsf", Call db.Compact End If dateTime ) Then © InterTrust Co. Тел. (095)9567928 Встроенные классы LotusScript u Java 410 Пример 10, То же самое делает Java-агент. DbDirectory dir = session.getDbDirectory("Server1/Acrne/RU"); DateTime dt = session.createDateTime("Today"); dt.setNow(); dt .adjustDay (-1}; Database db = dir.openDatabaselfModified("quack", dt) ; if (db !== null) { System, out. println ( "Compacting databases"); db . compact (); } else System.out.println("Database not modified in past day"); 3.5.1. Свойства, доступные из интерфейса клиента или администратора Свойство Title - «название базы» LotusScript: title$ = notesDatabase.Title notesDatabase.Title = title$ Java; String title. = Database.getTitleQ void Data base.setTMe(String title) Позволяет получить или изменить название базы (тип String). Учтите, что нельзя изменить название базы, в которой происходит выполнение скрипта или Java-агента. Свойство FileName - «имя файла» -.••.. /. • . : - : ..- .'. •-" ' • , . . . . . LotusScript: file'Name$ ~ nolesDatabase.fileN-лте Java: String fileName = Database.getFileNsimeQ Имя файла базы, включая расширение (обычно .NSF), но не включая каталоги относительно каталога данных Notes (тип String). Пример 1. Строковая переменная file получит значение "Names.nsf'. Dim db As New NotesDatabase( "Domino/Org/RU", file As String file = db.FileName "Names.nsf" ) Dim Пример 2. Строковая переменная file получит значение "ReadMe.nsf". Dim db As New NotesDatabase( "Domino/Org/RU", file As String file = db.FileName "doc\ReadMe.nsf" ) Dim Пример 3- Если Java-агент выполняется в базе "WDb\Education\JavaLotusScriptEx.nsf", им будет выведено сообщение «Database "Java&LScript Classes - примеры" has the file name JavaLotusScriptEx.nsf». // Java-Database/FileName Database db = agentContext.getCurrentDatabase(); String title = db.getTitleO ; String name = db.getFileName(); System.out.println("Database \"" + title + "\" has the file name " + name); СвойствоFilePath - «путь и имя файла» . '.••.••".-•••. v •'•'•••'• * ' :"• • ; ;••:••• '-'-.••• : LotusScript: pathS - notesDatabase.FilePatb Java: Stringpath = Database.geiFilePntbQ . ::. Имя файла базы (тип String), включая каталоги и расширение (обычно .NSF). Если база данных находится на станции, возвращаемый «путь» начинается с буквы диска и включает © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: ©-формулы, LotusScript, встроенные классы LotusScript и Java 411 все каталоги, например, C:\Lotus\Notes\data\dir\subdir\db.nsf. Если база данных находится на сервере, возвращается путь относительно каталога данных Notes, например, dir\subdir\db.nsf. Пример 1. Строковая переменная path! получит значение "Names.nsf (база находится на сервере), а переменная path2 - "D:\Notes50\Data\Narnes.nsf" (база «локальна»). Dim dbl As New NotesDatabase( "Domino/Org/RU", "Names.nsf" ) Dim db2 As New NotesDatabase( "", "Names.nsf" ) Dim pathl, path2 As String pathl = dbl.FilePath path2 = db2.FilePath Пример 2. Строковая переменная pathl получит значение "doc\ReadMe.nsf" (база на сервере), а переменная path2 - "D:\Notes50\Data\doc\ReadMe.nsf (база «локальна»). Dim dbl As New NotesDatabase( "Domino/Org/RU", "doc\ReadMe.nsf" } Dim db2 As New NotesDatabase( "", "docAReadMe.nsf" ) Dim pathl, pat.h2 As String pathl = dbl.FilePath path2 = db2.FilePath Пример З. Агент LSDatabaseFilePath, находящийся в расположенной на сервере базе OursDBs\WDb\Education\JavaLotusScriptEx.nsf и запускаемый из броузера по URL http://domino500/OursDBs/WDb/Education/JavaLotusScriptEx.nsf/LSDatabaseFilePath?OpenAgent, вернет в броузер страницу с текстом «FilePath=OursDBs\WDb\Education\JavaLotusScriptEx.nsf» . Sub Initialize Dim s As New NotesSession Dim db As NotesDatabase . Set db ~ s.CurrentDatabase Print "<b>FilePath=";db.FilePath;"<7b>" End Sub . . ' - , - . - ' Пример 4. Если Java-агент выполняется в базе "OursDBs\WDb\Eiducation\JavaLotusScriptEx.nsf', им будет выведено сообщение «Database "Java&LScript Classes - примеры" has the file path OursDBs\WDb\Education\JavaLotusScriptEx.nsf». // Java-Database/FilePath Database db = aqentContext,getCurrentDatabase(); String title = db,getTitle(); String path = db.getFilePath(); System.out.println("Database \"" + title + "\" has the file path " + path); Свойство Server - «сервер» LotusScript: serverName$ - notesDatabase.Server Java: String serverName ~ Database.getServerQ Имя сервера (тип String), на котором размещается база, или пустая строка (""/null), если база расположена локально. Пример. Скрипт определяет, находится ли текущая база на сервере или на станции. Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase ' If ( db.Server - "" ) Then Messagebox( "Это локальная база" ) Else Messagebox( "Это база на сервере " & db.Server ) End If © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript u Java 412 Свойство ReplicalD - «идентификатор реплики» LotusScript: id$ = notesDatabaseJR.epli.caID Java: String id = Databose.geiReplicalDQ 16-и символьная комбинация букв и цифр (тип String), представляющая идентификатор реплики этой базы. Все реплики этой базы имеют такой же идентификатор реплики, а копии -разные идентификаторы. Пример. Скрипт выводит в окне ID реплики текущей базы. Например, нечто подобное "852561C1004D958F". Dim session As New NotesSession Dim db As NotesDatabase Set db = sessi.on.CurrentDataba.se Messagebox( db.ReplicalD ) Свойство Created - «время создания базы» LotusScript: date V - notesDatabase.Created Java: Date Time date = Z)ara/>a$e.getCreated() Дата-время создания базы (в LotusScript тип Variant of type DATE, в Java - объект класса DateTime). Свойство LastModified - «время последней модификации базы» LotusScript: date V ~ notesDatabaseJLasiM.odified Java: DateTime date = Z)ata/>ase.getLastModified() Дата-время (в LotusScript тип Variant of type DATE, в Java - объект класса DateTime) последней модификации базы. Свойство Size - «размер в байтах». . :. ... LotusScript: size# = notes Database.Size Java: double size — Database.getSizeQ . : . . . : . . . . . . . -..: •" ' -- .. ; • .: Размер (тип double) базы в байтах. Свойством можно пользоваться для неоткрытой базы. Пример. Скрипт определяет размер текущей базы. Dim Dim Set Dim size session As New NotesSession db As NotesDatabase db = session.CurrentDatabase size As Double • . •-• db. Size Свойство SizeQuota - «квота на размер базы в Кбайтах» LotusScript: quota& = notesDatabase.SizeQuota noiesDatabase.Si'i.eQiiQt'A ~ quota& Java: int quota - Database,getSizeQuotaQ void Databose.setSizeQuota(int quota) © InterTrust Co. Тел. (095) 9567928 . - Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 413 Позволяет определять ранее установленное или устанавливать новое ограничение на размер базы («квоту») в Кб (в LotusScript тип Long, в Java - int). Если ограничение для базы не было установлено, свойство возвращает 0. Для установки свойства владелец агента или приложения должен иметь доступ администратора к серверу, на котором находится база. @ Свойство MaxSize - «максимально возможный размер базы в Кбайтах» LotusScript: size# - notes Database.MaxSize Java: long .size ~ Database.getMaxSizeQ Выбранный при создании базы ее максимально возможный размер (тип Double/Long) базы в Кб. Пример. Скрипт для текущей базы выводит размер, ограничение на размер («квоту») и максимально возможный размер. Dim session As New NotesSession Dim db As NotesDatabase Set. db = session. CurrentDatabase Print "Database size is: ", db.Size Print "Database Quota is: ", db.SizeQuota, "K" Print "Database Maximum Size is: ", db.MaxSize, "K" Свойство PercentUsed - «% использования дискового пространства базы» LotusScript: used# = notesDatabase.Percentllsed Java: double used = Database.getPercentUsed() Процентное отношение (тип Double) общего размера базы к размеру пространства в базе, действительно занятого данными. Операция уплотнения базы (Compact) устраняет из базы свободное (не занятое данными) пространство и «доводит» данное отношение почти до 100%. Свойство Categories - «категории в каталоге баз» LotusScript: categoryList$ — notesDalaba.se.Categories notes Database.Categories ~ categoryList$ Java: String categoryList =- Z)atoЈdwe.getCategQries() void Database.setC№tegaries(String categoryList) Категории, в форме строки, «в которых» база появляется в каталоге баз (CATALOG.NSF) или базе типа Database Library, Если категорий несколько, они должны разделяться в строке запятыми или точками с запятой. Свойство не требует, чтобы база данных была открыта. В окне свойств базы можно видеть поле с меткой "Categories:" , в котором и задаются категории для базы. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 414 Puc. 3.14 Категории для базы В следующем окне дан фрагмент вида Databases by Category базы данных CATALOG. NSF, |Ы » /^нс. 3. / Категории в виде Databases by Category базы CATALOG.NSF Пример 1. Скрипт выводит в диалоговом окне все категории текущей базы. Dim session As; New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase Messagebox( db.Categori.es ) Пример 2. Java-агент выводит категорию текущей базы. ./,/ Java -Database /Categories © InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 415 Database db -= agentContext.getCurrentDatabase{); String title - db.getTitle(}; String cat = db.getCategories (); if (cat != null) System.out.println("Database \"" + title + "\" has the categories: " + cat); e 1s e System . out; .println ( "Database V" r title + "\" has no categories"}; Пример З. Скрипт «присваивает» категорию "Application Template" текущей базе. Dim session As New NotesSession Dim db As NotesDatabase Set db = sess.ion.CurrentDatabase db.Categories = "Application Template" Свойство DesignTempIateName - «имя шаблона, с которого базой наследуется дизайн».....: ''.'.-•.-'.• •.-•'•'••. • -•-. ,'"..•'.••'••'••''••"•.''.;•.....:.•••' " . •- • • •'.-.-.;.. . LotusScript: пате$ — ?zofesData6ase.DesignTemplateName Java: String name ~ Z)a/a6ase.geffiesignTemplateName() Имя шаблона (тип String), из которого база наследует дизайн. Это текст из поля с меткой Template Name под «выбранной» опцией Inherit design from template в окне свойств базы (Рис. 3.14). Если база не наследует дизайн, возвращается ""/null. Если база наследует только отдельные элементы дизайна, например, только некоторые формы, но не весь дизайн целиком, также возвращается ""/null. Пример 1. Скрипт определяет имя шаблона, из которого наследует дизайн база MAIL\Dlvanov.NSF. Судя по имени файла базы, вероятно, это «почтовый ящик», и метод может вернуть "StdR46Mail", если только владелец базы не отказался от наследования дизайна или не использует свой собственный шаблон. Dim db As New NotesDatabase( "Domino/Org/RO", template$ = db.DesignTempIateName "mail\DIvanov.nsf" ) Пример 2. Java-агент выводит имя шаблона, с которого наследует дизайн текущая база. // Java-Database/DesignTempIateName Database db = agentContext.getCurrentDatabase( ) ; String title = db.getTitle(); String template = db.getDesignTemplateName(); if(template != null) System.out .println ("Database \"" + title + "\" inherits its design from " + template); else System, out .print] n ( "Database V" + title -t- " \ " did not inherit its design from a template"); Пример З. Подпрограмма отправляет менеджерам всех баз почтовые сообщения с предупреждением о том, что завтра дизайн-шаблон их баз будет изменен. Параметрами подпрограммы являются имя сервера и имя файла базы, являющейся шаблоном (например, MAIL46.NTF для шаблона "StdR46Mail"). Скрипт сначала определяет название шаблона, а затем в цикле перебирает все базы на сервере, и для тех, у которых название дизайн-шаблона совпадает с данным, отправляет письмо всем ее менеджерам. Sub templateNotification( server As String, file As String ) Dim templateDb As NotesDatabase Dim tempiateName As String Dim db As NotesDatabase © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript u Java 416 D im d irecto r y A s N o te sD b D ire c to r y Dim doc As NotesDocument Set teraplateDb = New NotesDatabase ( server, file ) teinplateName = templateDb. TemplateName Set directory - New NotesDbDirectory( server ) Set db = directory.GetFirstDatabase( DATABASE ) While Not ( db Is Nothing ) If ( db.DesignTemplateName = template'Name ) Then Call db.Open( "", "" ) Set doc = New NotesDocument( db ) doc. Form ••= "Memo" doc. Subject = "Template changes in " & teinplateName doc.Body = "The template " & templateName & _ " will be modified tomorrow." Call doc.Send( False, db.Managers ) End If Set db — directory. GetNextDatabase Wend ^ End Sub . Вызов этой подпрограммы мог бы выглядеть так: Call templateNotification ( "Doraino/Org/RU", "mai!46.ntf" } Свойство TemplateName - «название шаблона» LotusScript: name$ -• notesDatabase.TemplateName Java: String name = Z)ate/>os<?.getTemplateName() Если база является шаблоном, свойство возвращает название шаблона (тип String). Это текст из поля с меткой Template Name под «выбранной» опцией Database is template в окне свойств базы (Рис. 3.14). Если база не является шаблоном (например, лишь наследует дизайн с другого шаблона, наследует дизайн поэлементно или вообще ниоткуда не наследует дизайн), возвращается пустая строка ("") в LotusScript или null в Java. Пример 1. Скрипт определяет название шаблона у входящей в поставку Notes базы MA1L50.NTF. Возвращается "StdR50MaiI". Dim db As New NotesDatabase( "", "rnailSO . nt f " ) Dim template As String template = db.TemplateName Messagebox ( template ) Пример 2. Подпрограмма по переданным в качестве параметров имени пользователя, сервера и файла базы создает новую базу - «почтовый ящик» для этого пользователя, используя при этом шаблон StdRSOMail. Свойство TemplateName используется для поиска базы, которая является этим самым шаблоном с названием StdRSOMail. Sub createMailFile( user As String, server As String, file As String ) Dim templateDb As NotesDatabase Dim mailDb As NotesDatabase Dim directory As New NotesDbDirectory( server ) Set templateDb -- director у. Get FirstDatabase ( TEMPLATE ) While Not ( templateDb.TemplateName = "StdRSOMail" ) Set templateDb = directory.GetNextDatabase Wend Call templateDb.Open( "", "" ) Set mailDb = templateDb.CreateFromTemplate( server, "mail\"+flie, True ) mailDb.Title = user + " Mail" Call mailDb.GrantAccess( "Administrators", ACLLEVEL_MANAGER } Call mailDb.GrantAccess( user, ACLLEVEL_EDITOR ) © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5: (а)-формулы, LotusScript, встроенные классы LotusScript и Java 417 If ( server <> "" ) Then Call maiiDb.GrantAccess( server, ACLLEVEL__MANAGER ) End If End Sub Пример вызова этой полпрограммы: Call createMailFile( "Denis Ivanov", "Domino/Org/RU" , "DIvanov.nsf" ) Свойство IsFTIndexed - «имеется ли индекс полнотекстового поиска» LotusScript: Java: flag = notesDatabase.lsҐ'Tmde-%.tid boolean flag - Database AsfTlndcxeuQ Возвращает true, если база имеет индекс полнотекстового поиска, или false, если не имеет. Пример 1. Java-агент проверяет, имеет ли база индекс полнотекстового поиска. // Java-Database/1sFTIndexed Database db = agentContext.getCurrentDatabase(); String title = db.getTitle(); if(db.isFTIndexed()) System.out.println("Database \"" + title + "\" is full text indexed"); else System.out.println("Database \""+title+"\" is not full text indexed"); Пример 2. Прежде чем выполнять запрос полнотекстового поиска, скрипт «аккуратно» проверяет, имеет ли база индекс полнотекстового поиска, Dim session As New NotesSession Dim db As NotesDatabase Dim collection As NotesDocumentCollection Set db = session.CurrentOatabase If db.IsFTIndexed Then Set collection = db.FTSearch( "hook* & *DLL", End If . 0 ) Пример З. Скрипт использует свойство IsFTIndexed для определения, какой метод следует использовать для создания коллекции документов из базы SALES.NSF, содержащих слово "press". Если база имеет индекс полнотекстового поиска, документы со словом "press" отбираются методом FTSearch. Иначе для отбора документов, содержащих слово "press" в поле Body, используется метод search. Полученная коллекция документов используется при создании объекта класса NewsLetler. Объект класса NewsLetter позволяет создать «обзорный» документ - документ, содержащий в поле Body ссылки (DocLink-и) на все документы из коллекции. Созданный обзорный документ сохраняется в базе как документ формы Search Summary. Dim db As New NotesDatabase( "", "sales.nsf" ) Dim collection As NotesDocumentCollection Dim newsletter As NotesNewsletter Dim doc As NotesDocument Dim dateTime As NotesDateTime Dim maxDocs As Integer maxDocs - 10 If db.IsFTIndexed Then Set collection = db.FTSearch( "press", maxDocs ) Else Set dateTime = New NotesDateTime( "" ) Set collection = db.Search( "@Contains( Body; ""press"" }", dateTime, maxDocs ) End If Set newsletter — New NotesNewsletter( collection ) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript u Java 418 Set doc = newsletter.FormatMsgWithDoclinks( db ) doc. Form. - "Search Summ.ary" Call doc.Save{ True, True ) Свойство IsMuItiDbSearch - «используется ли база при создании индекса полнотекстового поиска по многим базам» LotusScript: flag = notesDatahase.lsMultiDbSem'ch Java: boolean flag = Database.isMnltiDbSearchQ Возвращает true, если база имеет свойство MultiDbSearch, или false, если не имеет. Свойство означает, что по текстовой информации из данной базы создается индекс полнотекстового поиска для многих баз. Свойство «не запрещает» базе может иметь и собственный индекс полнотекстового поиска, хотя последнее обычно считают излишеством. Свойство LastFTIndexed - «время последнего обновления индекса полно текстового поиска» LotusScript: date V - notesDatabaseJL&siF'TIndexcd Java: DateTime date - Z)a/aia,ve.getLastFTindexed() Дата-время (в LotusScript - Variant of type DATE, в Java - объект класса DateTime) последнего изменения индекса полнотекстового поиска у базы, или 12/30/1899 в LotusScript или null в Java, если база не имеет индекса полнотекстового поиска. 3.5.2, Свойства, касающиеся уровня доступа к ба*е Свойство Managers-«массив менеджеров базы» LotusScript: stringArrayMgrs - notesDatabase.'Managers Java: Java. util. Vector mgrs = Z)otoЈa$(?.getManagers0 Список пользователей, серверов и групп (в LotusScript - Array of Strings, в Java Java.util.Vector с элементами типа String), имеющих к базе доступ менеджера. т Пример 1. Скрипт последовательно выводит в окне имя каждого менеджера базы. Dim session As New NotesSession Dim db As NotesDatabase Set db •= session. CurrentDatabase Forall m In db.Managers Messageboxf m } End Forall Пример 2. Java-агент выводит список имен всех менеджеров базы. import т ava.util.Vector; // Java-Database/Managers Database db = agentContext.getCurrentDatabase (); String title = db.getTitle{); Vector managers = db.getManagers(); int. size = managers . size (}; if (size == 1) System.out.println("Database \"" + title + "\" has 1 manager"); else System.out.println("Database \"" + title + "\" has " + size + " managers"); for (int i=0; i<size; i++) © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 419 { String name = (String)managers.elementAt(i); System.out.print In("Manager # " + (i + 1) + ": " + name); } Пример З. Скрипт кнопки (событие Click) предлагает пользователю отправить письмо со своими предложениями по данной базе всем менеджерам этой базы. Sub Click(Source As Button) Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Set db = session.. CurrentDatabase Set doc = New MotesDocument( db ) doc.Form = "Memo" doc.Subject = "Предложения по базе "+ db.Title doc.Body = InputboxS( "Введите ваши предложения: Call doc.Send( False, db.Managers ) End Sub ", db.Title ) Пример 4. Приложение состоит из двух баз, которые работают совместно. Необходимо обеспечить, чтобы в ACL у обоих баз был одинаковый список менеджеров. Скрипт выбирает всех менеджеров из одной базы и каждому из них обеспечивает доступ менеджера к другой базе. Учтите, что для выполнения своей работы скрипт «сам» должен иметь доступ менеджера во второй базе. Dim dbl As New NotesDatabase ( "Key West", "cserv \datadict.nsf" ) Dim db2 As New NotesDatabase ( "Key West", "cserv\calltrak.nsf" ) Forall mgr In dbl.Managers Call db2.GrantAccess( mgr, ACLLEVEL_MANAGER ) End Forall Свойство CurrentAccessLevel - «текущий уровень доступа к базе» LotusScript: Java: lcvel% = notes Database.Cur rentAccessLevel inl level = Database.getCurrentAccessLevel() Константа типа Integer/int, позволяющая узнать, каков текущий уровень доступа к базе. Возможные значения: * ACLLEVELJNOACCESS / ACL.LEVEL JNOACCESS - нет доступа, * ACLLEVEL DEPOSITOR / ACL.LEVEL ^DEPOSITOR - депозитор, * ACLLEVEL_READER / ACL.LEVEL READER - читатель, * ACLLEVEL_AUTHOR/ACL.LEVEL_AUTHOR-автор, * ACLLEVEL_ EDITOR / ACL.LEVEL EDITOR - редактор, * ACLLEVEL DESIGNER / ACL.LEVEL ^DESIGNER - дизайнер, ACLLEVEL MANAGER / ACL.LEVEL JV1ANAGER - менеджер. Если выполнение происходит на станции или «удаленно» (ПОР) на сервере, значение свойства CurrentAccessLevel определяется как уровень доступа к базе текущего пользователя. Если выполнение осуществляется на сервере, значение свойства определяется как уровень доступа к базе «владельца агента» (лица, последним модифицировавшего агента), а не сервера. * Пример 1. Скрипт определяет уровень доступа пользователя к текущей базе. Например, если пользователь, под ID-файлом которого работает станция, имеет к базе доступ автора, свойство вернет константу ACLLEVEL_AUTHOR. Dim session As New NotesSession Dim db As NotesDatabase © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 420 Dim level As Integer-Set db = session.CurrentDatabase level = db.CurrentAccessLevel Пример 2. Java-агент выводит уровень доступа пользователя к текущей базе. ./'/ Java -Database /CurrentAccessLevel db = agentContext.getCurrentDatabase(); String title = db.getTitle (); •. int level = db.getCurrentAccessLevel(); System.out.print("For database \"" + title + "\" you have "); switch(level) / i case(ACL.LEVEL_NOACCESS): System.out.print("No access"); break; case(ACL.LEVEL DEPOSITOR): System.out.print("Depositor"); break; case (ACL . LEVEL_READER) : System, out.. print ( "Reader" ) ; break; case(ACL.LEVEL_AUTHOR): System.out.print("Author"); break; case(ACL.LEVEL EDITOR): System.out.print("Editor"); break; case(ACL.LEVEL_DESIGNER): System.out,print("Designer"); break; case(ACL.LEVEL MANAGER): System.out.print("Manager"); break; default: System.out.print("Unknown"); break; } System.out.print(" accessXn"); 3.5.3, Свойства для получения объектов-потомков Свойство Replicationlnfo - «объект Replicationlnfo для базы» LotusScript: NotesReplication ~ notesDatabase.Replicationlnfo Java: Replication ri = Database.getReplicationlnfoQ Возвращает ссылку на объект класса [NotesjReplication. Подробности в описании класса [Notes (Replication. Свойство ACL - «список управления доступом базы» LotusScript: Set notesACL =• notesDatabase.AClj t Java: : ACL ad = Database.getACL() Список управления доступом (ACL) базы как объект класса [Notes] ACL. Пример 1. Скрипт получает ACL базы и, используя метод getFirstEntry класса NotesACL, получает доступ к первому элементу в ACL. Dim Dim Dim Set Set db As New NotesDatabca.se ( "Domino/Org/RU", "mail\user01. risf" ) acl As NotesACL entry As NotesACLEntry acl = db.ACL > entry = acl.getFirstEntry Пример 2. Скрипт получает ACL текущей базы и, используя метод getEntry класса NotesACL, получает доступ к элементу в ACL для группы Administrators. Dim Dim Dim Dim Set Set session As New NotesSession db As NotesDatabase acl As NotesACL entry As NotesACLEntry db = session.current Database acl = db.ACL © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Set entry — acl.getEntry( "Administrators" 421 ) Пример 3. Java-агент получает ACL текущей базы и, используя методы getFirstEntry и getNextEntry класса ACL, выводит имена всех содержащихся в ACL элементов. // Java-Database/ACL db = ag ent Conte xt.g etCurre ntD atabas e {); ACL acl = db.getACL(); ACLEntry entry = acl.getFirstEntry( ) ; do { System.out.println(entry.getName()); } while ((entry = acl.getNextEntry(entry)) null); != Свойство Agents - «массив агентов базы» LotusScript: Java: notesAgentArray — notesDatabase.Agents Java. util. Vector agents -• DataЈa5e.getAgents() Массив агентов, имеющихся в базе (в LotusScript тип Array of NotesAgents, в Java -java.util.Vector с элементами класса Agent). Если выполнение происходит на станции или «удаленно» (ПОР) на сервере, в массиве присутствуют как общие агенты, так и личные агенты текущего пользователя. Если выполнение осуществляется на сервере, в массиве содержатся только общие агенты. Пример 1. Скрипт определяет имя первого агента в текущей базе. Dim session As New NotesSession Dim. db As NotesDatabase Dim agent as NotesAgent • Set db =• session. Current-Database Set agent = db.Agents( 0 ) Messagebox agent,Name Пример 2. Java-агент выводит имена всех агентов из текущей базы. import java.util.Vector; // Java-Database/Aqents Database db = agentContext.getCurrentDatabase( } ; Vector agents = db.getAgents(); System.out.println("Agents in database:"); for (int i = 0; i < agents.size( ) ; i++) { Agent agent = (Agent.} agents . elementAt (i) ; System, out.. print In ( " " + agent. get.Naine ( ) ) ; \ Свойство Views -«массив видов и папок базы» LotusScript: Java: notesViewArray = notesDatabase.\iews java.util. Vector views = Database.getViewsQ Для базы, расположенной на сервере, возвращается «массив» общих видов и папок в базе. Для локальной базы в «массиве» присутствуют также личные виды и папки пользователя. В LotusScript это действительно массив типа Array of NotesViews, в Java - объект класса Java.util.Vector. Каждый элемент массива или «вектора» - объект класса [Motes]View, представляющий конкретный вид или папку. Пример 1. Скрипт последовательно выводит в окнах имена всех видов и папок из текущей базы. Определяется также вид, являющийся видом по умолчанию (default view). © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 422 Dim session As New NotesSession Dim cib As NotesDatabase Set db= session.CurrentDatabase For a 1 i v 11\ db. Vi ews If v.IsDefaultView Then Messagebox(v.Name & " - default view") Else Messagebox(v.Name) End If End Forall Пример 2. Подобно предыдущему, Java-агент выводит количество и имена всех видов и папок из текущей базы. import java.util.Vector; /'/ Java-Database/Views Database db = agentContext . get.CurrentDatabase ( ) ; Strinq title = db.getTitle ( ) ; Vector views = db.getViews(); int.- size — views . size ( ) ; System, out.. println ("Database \ " " + title + "\" has " + size + " views"}; for (int i = 0; i < size; i + 4-) { String name = ( (View) views , element At ! i )). get.Name {); System.out.println("View #" + (i + 1) + ": " + name); } Свойство Forms - «массив форм и субформ базы» LotusScript: Java: notesFormArray = notef>Database.Ґorms Java. util. Vector forms = Database.getFormsQ Массив форм и субформ, имеющихся в базе (в LotusScript тип Array объектов класса NotesForm, в Java -Java.util. Vector с элементами класса Form). Пример 1. Скрипт выводит список названий всех имеющихся в текущей базе форм. Dim session Аз New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase Forall form In db.Forms Messagebox form.Name End Forall ' , Пример 2. Java-агент выводит список названий всех имеющихся в текущей базе форм. import j ava.util.Vector; // Java-Database/Forms Database db = agentContext.getCurrentDatabase(}; String title = db.getTitle(); Vector forms = db.getForms(); inc. size = forms, size () ; System.out.println("Database \"" + title + "\" has " + size for (int i =-• 0; i < size; i + +) { String name = {(Form)forms.elementAt(i)).getName(); System.out.println("Form #" + (i+1) + "; " + name); } © Inter Trust Co. Тел. (095) 9567928 + " forms"); Lotus Domino R. 5: (шгформулы, LotusScript, встроенные классы LotusScript и Java 423 Свойство AHDocumcnts - «коллекция всех документов базы» LotusScript: Java: Set notesDocwnentCollection — nolesDatabase.AllDocaments DocwnentCollection collection ~ Database.getAllDocumentsQ Коллекция (объект класса [Notes]DocumentCollection) из всех документов в базе. Пользоваться этим свойством для поиска нужных документов следует осмотрительно, поскольку при большом количестве документов их последовательный просмотр часто занимает много времени. Для поиска документов более эффективны методы FTSearch или search, возвращающие коллекцию документов, удовлетворяющих заданному критерию поиска - обычно такие коллекции бывают относительно меньшего размера. В то же время использование свойства AllDocuments оказывается эффективнее применения метода search с формулой отбора @АП. Пример 1. Скрипт определяет количество документов в базе свойством Count класса NotesDocumentCollection. Dim Dim Dim Dim Set Set n = session As New NotesSessiori db As NotesDatabase collection As NotesDocumentCollection n As Long db -- session. CurrentDatabase collection = db.AllDocuments collect ion.Count Пример 2. Скрипт события Click отсоединяет все присоединенные файлы из поля Body всех документов базы в каталог c:\newfiles и удаляет их из поля Body. Для этого скрипт проверяет каждый документ в коллекции из всех документов базы, и, если в документе содержатся встроенные OLE-объекты или присоединенные файлы, вызывает подпрограмму detachFiles, которая более детально проверяет наличие присоединенных файлов и отсоединяет их в заданный каталог. Sub Click (Source As Button) •. f Dim session As New NotesSession Dim db As NotesDatabase Dim collection As NotesDocumentCollection Dim doc As NotesDocument Set db session.CurrentDatabase Set collection = db.AllDocuments For i = 1 To collection.Count Set doc = collection.GetNthDocument( i ) If doc.HasEmbedded Then Call detachFiles{ doc ) End If Next ;: End Sub '.-.-. • . . • - • : ' ' Sub detachFiles( doc As NotesDocument ) • • ' Dim rtitem As Variant - ' • ' Set rtitem = doc.GetFirstltem( "Body" ) • . Forall о In rtitem. EmbeddedObjects -•-.-. If o.Type - EMBED^ATTACHMENT Then Call o.ExtractFile( "c:\newfiles\" & o.Source ) Call о.Remove Call doc.Save( True, True ) End If • .. • End Foraii •' .-.."•-•; End Sub ' ' • . © InterTrust Co, Тел. (095) 9567928 • 424 Встроенные классы LotusScript и Java Пример 3. Java-агент получает коллекцию из всех документов текущей базы, а затем в цикле для каждого документа выводит строку, содержащую номер документа в коллекции и содержимое поля Subject из документа. // Java-Database/AllDocuments Database db = agentContext.qetCurrentDatabase (); String title = db.getTitle {); DocumentCollection collection = db. getAUDocuments () ; System, out .print.ln ("Database \"" -t- title + "\" has " + collection.getCount() + " documents"); Document doc; for (int. i ~ 1; i <— dc. getCount () ; i + +) i; doc = collect ion.getNthDocument (i); // «Первый» документ в DocumentCollection имеет индекс 1 System, out. print In ( "Document #" + i + " : " +-doc . getltemValue ( "Subject. " ) ) ; Свойство UnprocessedDocuments - «коллекция необработанных документов»LotusScript: Java: Set notesDocumentCoUection ~~ woteA'Azta^ase.UnprocessedDocuments DocumentCollection coll = AgentContext.getUnprocessedDocmnentsQ Возвращает коллекцию документов (объект класса [Notes]DocumentCollection) из данной базы, которые текущий агент «рассматривает» как «необработанные» ("unprocessed"). Свойство имеет смысл только для агента (или действия по виду). Во всех иных контекстах свойство возвращает пустую коллекцию документов. В LotusScript свойство может применяться только к объекту класса NotesDatabase, полученному свойством CurrentDatabase объекта класса NotesSession. Если же объект класса NotesDatabase был получен не свойством CurrentDatabase, возникает ошибка. Вероятно, во избежание недоразумений с контекстом применимости в Java свойство UnprocessedDocuments являются членом класса AgentContext, а не класса Database. Это очень часто используемое свойство - ведь первый вопрос, с которым вы сталкиваетесь при разработке агента или акции по виду, заключается в определении множества (коллекции) документов, которые следует обработать. Множество документов, включаемых свойством в коллекцию, зависит от типа агента. Кроме того, если в «построителе агентов» был задан дополнительный поисковый критерий, включаемые в коллекцию документы должны удовлетворять еще и этому критерию. Последнее для простоты не оговаривается, но подразумевается в нижеследующем. * Если агент определен как работающий по новым или модифицированным с момента его предыдущего запуска документам (All new and modified documents since last run), свойство UnprocessedDocuments возвращает все документы, которые «не отмечены» агентом «как обработанные». Дело в том, что вы должны использовать метод updateProcessedDoc класса NotesSession/AgentContext для «отметки» каждого документа, обработанного агентом такого типа. Из этого следует, что свойство UnprocessedDocuments просто возвращает те документы, у которых нет отметки об обработке, «ранее созданной» этим же агентом. • Если агент определен как работающий по выбранным в виде документам (Selected documents), свойство UnprocessedDocuments возвращает все выбранные (отмеченные пользователем «галочкой» или текущий документ, когда ничего не отмечено «галочкой») документы. Использование updateProcessedDoc в такой ситуации не имеет смысла и эффекта. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R, 5: (Sf-формулы, LotusScript, встроенные массы LotusScript и Java * • * 425 Если агент определен как работающий по всем документам н виде (All documents in view), свойство UnprocessedDocuments возвращает все документы из текущего вида. Использование updateProcessedDoc в этой ситуации не имеет смысла и эффекта. Если агент определен как работающий по всем документам в базе (A1J documents in database), свойство UnprocessedDocuments возвращает все документы из текущей базы. Использование updateProcessedDoc в этой ситуации не имеет смысла и эффекта, Если агент определен как работающий по всем непрочитанным пользователем документам из вида (All unread documents in view), свойство UnprocessedDocuments возвращает все непрочитанные текущим пользователем документы из текущего вида. Использование updateProcessedDoc в этой ситуации не имеет смысла и эффекта. • Если агент определен как работающий только по текущему документу в виде (Run once), UnprocessedDocuments возвращает коллекцию из одного этого документа. Для такого агента отсутствует дополнительный поисковый критерий, а использование updateProcessedDoc не имеет смысла и эффекта. • Если агент определен как работающий по поступающим почтой документам (Newly received mail documents), no созданным новым или модифицированным в базе документам (Newly modified documents) или по документам, добавленным в базу из буфера обмена (Pasted documents), свойство UnprocessedDocuments возвращает только поступившие почтой документы, созданные новые или модифицированные документы или документы, добавленные в базу из буфера обмена, но только при условии, что они ещё «не отмечены» агентом «как обработанные». И вы после обработки каждого документа должны использовать метод updateProcessedDoc из класса NotesSession/AgentContext для «отметки» этого документа, «как уже обработанного» агентом. Если скрипт или агент является частью действия по виду (View action), свойство UnprocessedDocuments возвращает все выбранные в виде документы. * Пример 1. Скрипт действия по виду (view action) позволяет пользователю одобрить («положительно завизировать») сразу все выбранные Б виде документы. Коллекция выбранных пользователем документов просматривается в цикле, и, если документ «требует одобрения» данным пользователем, т.е. в его поле Approver содержится имя этого пользователя, то полю Approved присваивается значение "Yes". Dim session As New NotesSession Dim db As NotesDatabase Dim collection As NotesDocumentCollect.ion Dim doc As NotesDocument Set. db = session. C'urrentDatabase Set collection = db.UnprocessedDocuments For i -= 1 To col lection. Count Set doc = collection. GetNthDocumer.it ( i ) Set item = doc.GetFirstItem( "Approver" ) If item,Contains ( session.UserName ) Then doc.Approved = "Yes" Call doc.Save( False, True ) End If K'ext Пример 2. Java-агент, запускаемый действием по виду (view action), выводи! количество выбранных пользователем в виде документов и текст их поля Subject. /./ Java- agent Con text /UnprocessedDocuments DoauatentCollection dc = agentContext. getUnprocessedOocuments () / System, out.print-In ( "Count = " + dc.get Count( ) ) ; Document doc = dc.getFirstDocument(); while (doc I— null) { © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 426 } System.out.printIn(doc .getItemValueString ("Subject")); doc = dc.getNextDocument(); ' 3.5,4. Прочие свойства Свойство Parent - «родитель» LotusScript: Set notesSession - notesDatabase.Parent .. Java: Session session =- Database.geiParentQ Объект класса [NotesJSession, являющийся «родителем» данного объекта [NotesjDatabase. Свойство IsOpen - «открыта ли база» LotusScript: Java: flag ~ notesDatabase.lsOpen boolean flag - Database.isOpenQ Возвращает true, если объект класса [Notes]Database открыт, иначе false. Если объект [NotesjDatabase открыт, доступны все его свойства и методы. Если же объект не открыт, для чтения доступны лишь немногие из его свойств, в частности Categories, DelayUpdates, DesignTemplateName, FileName, FilePath, IsOpen, IsPrivateAddressBook, IsPublicAddressBook, Parent, ReplicalD, Server, SizeQuota, TempIateName, Title. Методы getFirstDatabase и getNextDatabase класса [Notes]DbDirectory и getAddressBooks класса [NotesJSession возвращают «закрытые базы». Чтобы открыть базу, можно воспользоваться методом open класса [NotesjDatabase, Свойство IsPrivateAddressBook - «личная ли адресная книга» LotusScript: flag - «ofcsDa?aЈave.IsPrivateAddressBook Java: boolean flag = Z)a/aia5e.isPrivateAddressBook() . . .; ..: ............ . Возвращает true, если данная база является личной адресной книгой, иначе false. Свойство имеет смысл только тогда, когда объект класса [NotesjDatabase был получен свойством AddressBooks объекта класса [NotesJSession. При других способах получения объекта класса [Notes]Database это свойство вообще не имеет никакого смысла, но возвращает false. Свойство IsPublicAddressBook - «общая ли адресная книга» LotusScript: Java: flag = «o/es.DatoAase.IsPubHcAddressBook boolean flag = Ј>ata6ase,isPublicAddressBook() Возвращает true, если данная база является общей адресной книгой, иначе false, В остальном аналогично свойству IsPrivateAddressBook. © Свойство IsDirectoryCatalog - «типа ли Directory Catalog» LotusScript: flag - /2o/esDataЈa$'e.IsDirectoryCatalog Возвращает true, если данная база является адресной книгой типа Directory Catalog, иначе false. Имеется в виду база типа Light Address Book, обычно созданная по шаблону с именем Lightweight Directory (файл DIRCAT.NTF с именем базы Directory Catalog). © InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 427 Свойство имеет смысл только тогда, когда объект класса NotesDatabase был получен свойством AddressBooks объекта класса NotesSession, а затем был явно открыт. При других способах получения объекта класса NotesDatabase это свойство вообще не имеет никакого смысла, но возвращает false. Пример. Скрипт получает «список» всех адресных книг и для каждой адресной книги «сообщает», является ли она адресной книгой типа Directory Catalog и где расположена. Dim session As New NotesSession Dim books As Variant books = session.addressbooks Forall b In books If b.IsPrivateAddressBook = True Then Call b.open("","") If b. IsDirectoryCatalog •= True Then Messagebox b.Title+" Directory Catalog on Local" Else Messagebox b.Title+" NAB on Local" End If Else Call b.open("", ""> If b. IsDirectoryCatalog - True Then Messagebox b.TitIe+" Directory Catalog on Server" Else Messagebox b. Title-)-" NAB on Server" End If End If End Forall © Свойство FolderRefereneesEnabled - «поддерживаются ли базой ссылки на ПаПКИ» ' LotusScript: •' '. • :'• : • . • - . ' • . - ; • . . ' • • • '".' -:' : '.- ••'. • •• ' " ' " . ' . ''' • flag = notcsDatabase.VolderRcferencesEnabled notesDatabase.'FolderReferencesE.nabled =flag Java: boolean flag ------ /)<3toAa$e.getFoIderReferencesEnabled() void DataЈaye.setFoIderReferencesEnabled(Јoofean flag) He все базы поддерживают ссылки на папки (folder references). Поэтому прежде чем для конкретного документа из базы пытаться получить 4- свойством FolderReferences класса [NotesJDocument названия содержащих этот документ папок (чтобы «узнать, в каких папках этот документ находится»), необходимо проверить, поддерживает ли вообще база такую возможность. Эта проверка осуществляется свойством FolderReferencesEnabled. True означает, что ссылки на папки поддерживаются базой, a false - что не поддерживаются. Реализуется же данная возможность посредством скрытых видов с названиями SFolderlnto и $FolderReflnfo. Эти виды, как элементы дизайна, необходимо предварительно скопировать в вашу базу данных из шаблона почтового ящика версии 5.0 - «простого включения» свойства FolderReferencesEnabled недостаточно. Естественно, при этом и ваша база данных должна быть формата R5 (ODS version 41). Пример. Скрипт создает в базе новый документ, помещает его в папки с именами "viewl", "view2" H"view3", а затем для каждого документа этой базы выводит названия содержащих его папок и их количество. Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument . : . . . . . . © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 428 Set db = session.CurrentDataba.se If (db. FolderReferencesEnabled) Then. Messagebox ("Folder References enabled") Else Messagebox ("Folder References are not enabled") Messagebox ("Enabling Folder References") db.FolderReferencesEnabled = True End If Set doc = db.CreateDocument If Not (doc Is Nothing) Then Call doc.AppendltemValue("Name", "Test Document Name") Call doc.AppendltemValue("Topic", "Test Document Topic") Call doc:. Save (True, True) Messagebox ("Adding document to views") doc.PutlnFolder("viewl") doc.PutlnFolder("view2") doc.PutlnFolder("view3") Call doc.Save(True, True) End If Dim doccoll As NotesDocumentCollection Set doccoll = db.AllDocuments Set, doc = doccoll. GetF'irstDocument While Not (doc Is Nothing) Л i=0 J Fora.ll FolderRef erence In doc. FolderReferences i-i + 1 Print doc.noteid, " ", i, " ", FolderReference End Fora11 Set doc = doccoll.GetNextDocument(doc) Wend .'.•• Свойство DelayUpdates/IsDelayUpdates - «отложенные'изменения» " : • • • - . . • . ..LotusScript: flag ~ notesDatabtise.DelayUpu&tes notesDatabase.DelayUpdates ~flag Java: boolean flag = Database,isT)elayVpd&tes() void Database.seiDelnyVpdsites(boolean flag) Определяет способ передачи на сервер выполняемых клиентом операций по изменению (сохранению или удалению) документов в базе, находящейся на сервере. Если свойство равно false (значение по умолчанию), изменения документов будут передаваться на сервер синхронно, т.е. приложение (агент, скрипт, апплет...) на клиенте, изменив, например, объект [NotesJDocument и вызвав для него метод save, будет «дожидаться» завершения передачи связанной с этим изменением информации на сервер, прежде чем «в цикле» перейти к обработке следующего документа. Такой вариант увеличивает время выполнения приложения на клиенте, однако гарантирует внесение в базу всех выполненных клиентом изменений до момента его краха, если такое случится. Если свойство равно true, изменения документов будут передаваться на сервер асинхронно («отложенно»), т.е. приложение на клиенте, изменив, например, объект [NotesJDocument и вызвав для него метод save, не будет «дожидаться» завершения передачи связанной с этим изменением информации на сервер, а сразу перейдет к обработке следующего «в цикле» документа. «Заказы на изменения» будут кэшироваться клиентом, а их © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @~формулы, LotusScript, встроенные классы LotusScript и Java 429 передача на сервер будет происходить «пакетом» лишь спустя некоторое время. Этот вариант уменьшает время выполнения приложения и способствует улучшению производительности клиента, однако в случае краха клиента «заказы на изменения», находящиеся в его кэше, могут быть потеряны. Значение свойства не сохраняется в самой базе - его необходимо устанавливать всякий раз после открытия базы перед внесением в нее изменений. Пример I. Скрипт устанавливает свойство Delay Updates. Dim session As New NotesSession Dim db As NotesDatabase Set db session.CurrentDatabase db. Delay-Updates = True Пример 2. Java-агент, начиная свою работу, устанавливает свойство DeiayUpdates в значение true, если разработчик «написал DelayUpdat.es» в поле комментариев агента. / / Ja va - Dat. aba s e / De 1 ayUpdat es Agent agent. -• agentContext . getCurrentAgent () ; Database db = agentContext.getCurrentDatabase( ) ; if (agent.getComment() != null) if (agent.getComment() .equals{"DeiayUpdates") ) db,set Del a yUpdat es ( t r ue ); System.out.println("Delay is " + db.isDelayUpdates()); - ' updates 3.5.5. Методы для создания новых баз, копий и реплик баз Метод create - «создать пустую базу» LotusScript: Call notesDatabase.create( xerverS, dbftle$, openflag [, maxSize% ] ) Java: Database db = DbDirectory.createDntabase(String dbfile) Database db = (DbDireclory.createDatabase(String dbfile, boolean open) Метод create создает новую «пустую» (точнее, с одним «безымянным» видом, как и при создании новой базы без выбора шаблона, т.е. по «шаблону -Blank-») базу на указанном сервере в указанном файле. Параметр server (тип String) - имя сервера или пустая строка (""), если нужно создать локальную базу. Параметр dbfile (тип String) - имя файла создаваемой базы. Если параметр openflag равен true, то метод должен открыть созданную базу (объект-класса [NotesJDatabase), если false - открывать объект не требуется. Параметр maxSize добавлен в версии 5.0 и задает максимально допустимый размер базы в Гбайтах (допустимые значения 1, 2, 3, 4), когда база создается на сервере версии 4.x. Если объект notesDatabase перед применением метода уже был связан с базой на сервере или станции (например, если объект notesDalabase был получен методом New с непустыми параметрами), то оба параметра server и dbfile метода create должны быть пустыми строками ("")• Если файл базы с указанным именем на указанном сервере уже существует, в LotusScript возникает ошибка "File already exists". Агент, выполняющийся на сервере, может создать базу только на этом сервере, но не на других серверах. Такое поведение, возможно, вызовет у читателя некоторое недоумение в ситуации, когда оба сервера работают в пределах одной высокоскоростной локальной сети. Но оно представляется логичным, если серверы связаны друг с другом по коммутируемому соединению с использованием модемов, и, согласно документу 7 Connection, должны связываться только раз в неделю ночью по воскресеньям для выполнения репликаций. Справедливо «более широкое» высказывание: агент, выполняющийся на сервере, может © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 430 иметь доступ только к базам на этом сервере и не может иметь доступ к омам на других серверах. Если же скрипт выполняется на станции, он может создать базу на любом из серверов, к которым пользователь имеет соответствующий доступ/ При создании скриптов, выполняющихся на сервере, самый надежный способ - указывать имя сервера в виде пустой строки, что означает создание базы на этом же компьютере. Пример, Скрипт создает новую базу на сервере Domirio/Org/RU в файле inventry.nsf, открывает ее и присваивает ей название "Inventory Tracking". Dim db As New NotesDatabase( "", "" ) Call db.create( "Domino/Org/RU", "inventry.nsf", True ) db. Title -^-- "Inventory Tracking" Метод CreateFromTemplate - «создать базу по шаблону» LotusScript: Set notesDatabase — notesDatabase.createFromJ'emplstef serverS, cib/ileS, inheritFlag [, maxSize% } ) Java: Database db ~- Database.createFrom'Templa.te(String server, String dbfile, boolean inherit) База, к которой применяется метод, рассматривается как шаблон. По этому шаблону на сервере server в файле dbfile создается новая база - возвращаемое значение метода. Эта новая база будет содержать все элементы дизайна (формы, субформы, виды, навигаторы, поля, агенты...) и документы из шаблона. Если флаг inherit равен true, в свойствах созданной базы устанавливается наследование дизайна с шаблона, если false - не устанавливается. В ситуации, когда база, к которой применяется метод, шаблоном не является, в LotusScript новая база все равно создается посредством копирования элементов дизайна и документов из существующей. Однако в этой же ситуации в Java новая база будет создана «шаблону -Blank-», т.е. не будет содержать никаких элементов дизайна, кроме одного «безымянного» вида. Синтаксис и семантика параметров метода аналогичны параметрам метода create, и все замечания к методу create имеют силу и для этого метода. т Пример I. Скрипт создает базу по шаблону «Дискуссии». Поскольку шаблон и создаваемая база находятся на разных серверах, такой скрипт будет работоспособен только на станции. Dim template As New NotesDatabase( "Dominol/Org/RU", "discswSO.ntf" ) Dim db As NotesDatabase Set db = template.CreateFromTemplate( "Domino2/Org/RU", "suggest.nsf", _ True ) db.Title = "Suggestions for Giving Campaign" Пример 2. Java-агент создает базу по шаблону «Дискуссии». Поскольку шаблон и создаваемая база находятся на «локальном компьютере», агент будет работоспособен как на станции, так и на сервере. // J a v a -D a t a b a s e / c r e a t e Fr o mT e mp l a t e Database template - session.getDatabase(null, "discswSO.ntf"); Database db = template.CreateFromTemplate(null, "suggest", true); db.setTitle("Suggestions for Giving Campaign"); System, out. .println ( "V'Suggest ions for Giving CampagnV created"); Метод createCopy - «создать копию базы» LotusScript: . '.:.-. : ......... ... Set notesDatabase - notesDatabase.crenteCQpy( serverS, dbfileS © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java .-...Java: 431 [, maxSize% J ) Database db = Database.createCopy(Stri}ig server, String dbfile) Создает копию (но без документов) базы, к которой применяется метод. Копия получает из оригинала элементы дизайна, название базы и список управления доступом (ACL). Копия будет иметь другой по сравнению с оригиналом идентификатор реплики. Синтаксис и семантика параметров метода аналогичны соответствующим параметрам методов create и createFromTempiate. Замечания к методу create имеют силу и для этого метода. ACL оригинала копируется в новую базу, но если требуется изменить ACL копии, можно воспользоваться методами grantAccess и removeAccess. ., Пример 1. Скрипт создает копию (без документов) базы PURCHASE.NSF на сервере. Dim db, archiveDb As NotesDatabase Set db ;= New NotesDatabase ( "Domino/Org/RU" , "purchase . risf" ) Set archiveDb = db.createCopy( "Domino/Org/RU","archive\purchase.nsf" ) Пример 2. Скрипт переносит все документы, имеющие в поле age значение "old", в архивную базу. Если архивная база еще не создана, она создается методом createCopy. Dim session As New NotesSession Dim db As NotesDatabase Dim archiveDb As NotesDatabase Dim collection As NotesDocumentCollection Dim doc As NotesDocument Dim date'Time As New NotesDateTime ( "1/1/98" ) Set db = session.CurrentDatabase Set archiveDb = New NotesDatabase( "", "" ) archiveServer$ = "" archiveFile$ = "archiveV" + db.FileName If (Not(archiveDb.Open(archiveServer$, archiveFile$ ))) Then Set archiveDb = db. createCopy ( archiveServer$ , a.rchiveFile$ ) End If Set collection = db. search ( "age --- ""old"" ", dateTime, 0 ) For i = 1 To collection.Count Set doc = collection.getNthDocument( i ) Call doc.copyToDatabase( archiveDb ) Call doc.remove( False ) Next Пример 3. Java-агент создает «локальную» копию адресной книги. Этот агент работоспособен как на станции, так и на сервере. // Java-Database/createCopy Database db = session.getDatabase(null, "names"}; String title =• db . getTitie () ; Database db2 = db.createCopy(null, "names2"); db2.setTitle("Copy of names"); ~ ' System, out .pr.intln ("Database \"" + title + "\" copied locally"); Метод createReplica - «создать реплику базы» LotusScript: Set notesDatabase — notesDatabase.createRcp\ica( server$, dbfileS ) Java: Database db = Database.createRef>\Ka(String server, String dbfile) Создает новую реплику базы, к которой применяется метод, в новом местоположении. Новая реплика получает такую же ACL, как и оригинал. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 432 Синтаксис и семантика параметров метода аналогичны двум первым параметрам метода create и параметрам метода createCopy. Замечания к методам create и createCopy имеют силу и для этого метода. / Пример 1. Скрипт создает реплику текущей базы на сервере, ' Dim session As New NotesSession Dim db As Notes Database _ ., •. Dim replica As NotesDatabase Set db = session.currentDatabase Set replica = db.createReplica( "Domino/Org/RU", . "sales.nsf" . . ) Пример 2, Java-агент, выполняющийся на станции, создает реплику базы DOMLOG.NSF («Протокол обращений к Web-серверу Domino») с сервера на станцию. // Java-Database/createReplica Database db = session.getDatabase("Dornino/Orq./RU", "Dorolog"); String title = db.getTitle(); Database replica = db.createReplica(null, "Domlog"); System.out.println("Database \"" + title ' "\" has a. new local replica"); 3.5.6. Методы для «открытая» баз Метод open - «открыть базу» • • ' . . ' ' ' • . : . . - . . - • • • : ................ LotusScript: flag -~ notesDatabase.open( server$, db file $ ) Java: boolean flag — Database,opcnQ Database db ~-'-: DbDirectory,openDatsibase(S(rmg dbfile) Database db -~ DbDirecto?'y.openDatabase(Slring dbfile, boolean fauover) Открывает базу (более строго, объект класса NotesDatabase). Когда база открыта, доступны все ее свойства и методы. Параметр server$ (тип String) задает имя сервера, на котором находится база. Использование пустой строки ("") либо означает, что база размещена локально, либо что объект класса NotesDatabase уже связан с конкретной базой, а «сейчас» только открывается. Параметр dbfile$ (тип String) задает имя файла базы. Использование пустой строки означает, что объект класса NotesDatabase уже связан с конкретной базой, а «сейчас» только открывается. Возвращается true, если база существует и объект открылся, или false, если базы в данном местоположении нет. В LotusScript возможны два случая использования метода open. • • Объект класса NotesDatabase создан и уже связан с существующей базой. В этом случае вы должны либо задать оба параметра метода пустыми строками, например db.Open("", ""), либо указать их в точности такими, как они уже установлены в объекте класса NotesDatabase. Если же вы попытаетесь «переназначить» уже установленные в объекте сервер или файл, то получите сообщение об ошибке. Объект класса NotesDatabase создан, но еще не связан с существующей базой. В этом случае вы должны указать имя сервера (пустая строка вместо имени сервера теперь означает, что база расположена локально), и имя базы (оно не может быть в этом случае пустой строкой). В Java метод open класса Database не имеет параметров, что соответствует «первому случаю» - объект класса Database создан и уже связан с существующей базой. Однако © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 433 имеется подобный метод класса DbDirectory, при использовании которого имя сервера «уже было сообщено» при создании объекта DbDirectory, имя файла базы задается параметром dbfile (тип String), а параметр failover, если он равен true, требует предпринять попытку открыть базу на другом сервере-члене кластера, если ее не удалось открыть на первоначальном. Этот метод возвращает открытый объект класса Database или null, если реплику найти не удалось или она не открылась. Выполняемый код (скрипт, Java-агент, Java-приложение или апплет) должен иметь доступ к серверу, если база находится на сервере, и. доступ не ниже депозитора к открываемой базе. В противном случае возникает ошибка или генерируется исключение в связи с отсутствием доступа. Если код выполняется на станции, его доступ к базе совпадает с доступом пользователя, под ID-файлом которого работает станция. Доступ апплета зависит от того, как был аутентифицирован сервером клиент броузера. Если же код выполняется на сервере, его доступ обычно определяется как доступ лица, сохранившего последним данный код. Исключение из этого правила составляет выполняющийся на сервере агент с опцией «Run agent as Web user» - его доступ зависит от того, как был аутентифицирован сервером клиент броузера. Пример 1. Скрипт открывает первую базу, найденную на текущем компьютере (сервере или станции). Dim directory As New NotesDbDirectory( "" ) Dim db As NotesDataba.se Set db ^ directory.getFirstDatabase( DATABASE ) Call db.Open( "", "" ) Пример 2. Подобно предыдущему примеру Java-агент открывает первую базу, найденную на текущем компьютере. Текст агента приведен полностью, чтобы дополнительно продемонстрировать читателям, которые только начинают освоение Java, создание собственных методов в классе. import lotus.domino.*; public class JavaAgent extends AgentBase { • . public void isitopen(Database db) throws NotesException { if (db.isOpen{)) System.out.println("\"" + db.getTitle() + "\" is open"); else System.out .println ("\"" + db. getTitle () -t "\" is not: open"); } , public void NotesMain() \ } try { Session session = getSession(); AgentContext agentCcntext = session.getAgentContext(); /,/ Java-Database/open DbDirectory Dir = session.getDbDirectory(null); Database db = Dir.getFirstDatabase(DbDirectory.DATABASE); isitopen(db); db.open(); isitopen(db); ' } catch(Exception e) { e.printStackTrace{) ; } . . . . . . } Пример З. Скрипт открывает базу SALES.NSF на сервере. Dim db As New NotesDatabase( "", "" ) Call db.Open( "Domino/Org/RU", "sales.nsf" ) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 434 Пример 4. Скрипт пытается открыть на текущем компьютере базу archive\product.nsf. Если это не удается, он создает базу archive\product.nsf как копию базы product.nsf, и обеспечивает к ней доступ менеджера для Ivan Sidorov/Org/RU. Dim archiveDb As New NotesDatabase ( "", "" ) Dim originalDb As New NotesDatabase( "", "product.nsf" ) Dim collection As NotesDocumentCollection Dim doc As NotesDocumerit If ( Not ( archiveDb.Open( "", "archive\" & originalDb.FileName ) ) ) Then Set archiveDb = originalDb.CreateCopy( "", "archiveV & originalDb.FileName } Call archiveDb.GrantAccess{ "Ivan Sidorov/Org/RU", ACL_MANAGER ) End If . . - - Метод openWithFailover - «открыть базу на доступном члене кластера» LotusScript: flag - notesDatabase.openWMiFuilover( serverS, dbfileS } Java: Database db - DbDirectory.openfiatabase(Strmg dbfile, boolean failover) Метод openWithFailover аналогичен методу open, но предпринимает попытку открыть базу на другом сервере-члене кластера, если ее не удалось открыть на первоначальном в связи с неработоспособностью сервера, уменьшением индекса доступности сервера ниже заданного порога доступности или превышением допустимого количества работающих с сервером пользователей. Аналогом этого в Java выступает метод openDatabase класса Db Directory с параметром failover. Метод openByReplicalD - «открыть базу по идентификатору реплики» LotusScript: flag = notes'.Database.openByReplicaID( serverS , replicaID$ ) Java: Database db =- DbDirectory.openDatab&$<iByReplic'dlD(Strmg replicalD) Открывает на заданном сервере базу, имеющую заданный ID реплики, если она существует. Параметр serverS (тип String) - имя сервера или пустая строка (""), означающая, что база находится на текущем компьютере. Параметр replicalD (тип String) - идентификатор реплики базы. В LotusScript возвращаемое значение равно true, если реплика найдена и объект открылся, или false, если реплика не найдена или объект не открылся. В Java аналогичный метод имеется в классе DbDirectory и возвращает открытый объект класса Database или null, если реплику найти не удалось или она не открылась. Пример. Java-агент предпринимает попытку открыть базу по идентификатору реплики. // Java-Database/openDatabaseByReplicalD ,--. DbDirectory dir = session.getDbDirectory(null}; String rid = "852565D2000B5144"; Database db = dir.openDatabaseByReplicalD(rid); if (db !— null) System.out.println("help located and opened"); else System.out.println("help not found"); Метод openlfModffied - «открыть базу, если она была модифицирована» LotusScript; Java: flag = notesDatabase.openIfModiued( serverS, dbfileS, notesDateTime ) Database db - Z)/7D/rector>'.openDatabaseItModified(5/r/ng dbfile, Date Time date) © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 435 Открывает указанную базу, только если она была модифицирована после заданного момента времени. , В LotusScript параметр serverS (тип String) задает имя сервера, dhfileS (тип String) - имя файла базы, a notesDateTime (объект класса NotesDateTime) - «момент отсечки» (cutoff date) -если с этого момента времени в базе был изменен хотя бы один документ, база открывается, иначе нет. Возвращается true, если объект открылся, или false, если нет. В Java подобный метод имеется в классе DbDirectory и возвращает открытый объект класса Database, если хотя бы один документ в базе подвергался модификации после указанного момента времени, или null, если не подвергался, базу найти не удалось или она не открылась. Метод openMail - «открыть почтовый ящик» LotusScript: Call notesDatabase,openMail Java: Database db = jDM^iVectory.openMailDatabaseQ В LotusScript открывает объект класса NotesDatabase, связанный с почтовым ящиком пользователя. .. , ' ' ' " - . ' ' .- . В Java подобный метод применяется к объекту класса DbDirectory и возвращает открытый объект класса Database, связанный с почтовым ящиком пользователя, или null, если это не удапось. Использование обоих методов имеет смысл либо со станции пользователя (скрипт или Java-агент, выполняющийся на станции, может открыть базу на доступном сервере), либо на почтовом сервере владельца агента (поскольку агент,, выполняющийся на сервере, все равно не сможет открыть базу на другом сервере). . ... . * Если выполнение происходит на станции, местоположение пользователя устанавливается по информации из файла NOTES.INI. почтового ящика • Если выполнение осуществляется сервером, владельцем агента считается лицо, последним модифицировавшее данный агент. Местоположение почтового ящика владельца устанавливается поиском в общей адресной книге по имени владельца. Пример. Скрипт определяет и выводит в диалоговом окне название базы и имя сервера для почтового ящика пользователя, на станции которого происходит выполнение. Dim db As New NotesDatabase( » " , " » ) Call db.OpenMail Call db. Open { "", "" ) Messagebox ( db. Title & " on server " & db. Server ) .. • . • - • - ..... Метод openURLDb - «открыть базу Web Navigator» . ,.-...;;,:..:; :.:::... . • .... ; .. :.-;..->-.•:.-..:;:.. LotusScript: flag = notesDatabase.openVKLDb Java: Database db = Sesi'/on.getURLDatabaseQ Открывает объект класса [NotesJDatabase, связанный с базой Web Navigator. В LotusScript, если объект уже был связан с другой базой, та база сначала закрывается. Возвращает true, если операция завершилась успешно, или false иначе. . В Java подобный метод имеется в классе Session и возвращает открытый объект класса Database, связанный с базой Web Navigator, или null, если это не удалось. ©InterTrust Co. Тел. (095)9567928 Встроенные классы LotusScript и Java 436 3.5.7. Методы для получения документов Метод createDocuraent - «создать новый документ» LotusScript: Java: Set notesDocument = notesDatabase.createDocuniKiit Document doc = Database.createDocnmentQ Создает в базе, к которой применяется метод, новый документ, и возвращает объект класса [NotesJDocument, представляющий этот документ. Чтобы созданный документ сохранился в базе, не забудьте применить к нему метод save. Для получения дополнительной информации смотрите класс [Notes]Document. Метод getDocumentByID - «получить документ по Note ID» LotusScript: Set notesDocument = notesDatabase.geiDocumentBylD( notelDS ) Java: Document doc = Database.getDocumentBylD(String notelD) По заданному параметром notelD (тип String) идентификатору документа (Note ID) находит документ в базе и возвращает объект класса [NotesJDocument, представляющий этот документ. Идентификатор документа может быть получен свойством NotelD объекта класса [NotesjDocument. Он представляется 8-и символьной строкой наподобие "000020FA". Идентификатор документа, возвращаемый @-функцией @NoteID, содержит префикс "NT", т.е. выглядит наподобие "NT000020FA". Метод getDocumentByUNID - «получить документ по UNID» LotusScript: Java: Set notesDocument = notesDatabase,geiDocumeniByUNTD( unid$ ) Document doc = Database.ge{DQCumeniByUNIJ)(Strmg unid) По заданному параметром unid (тип String) универсальному идентификатору (UNID) документа находит документ в базе и возвращает объект класса [Notes]Document, представляющий этот документ. Универсальный идентификатор документа может быть получен свойством UniversallD или ParentDocumentUNID объекта класса [Notes]Document. Он одинаков для документа во всех репликах базы и представляется 32 -х символьной строкой наподобие "CE44267695A4F344C32562CA005C80DB". Пример 1. Скрипт демонстрирует два варианта получения документа-родителя по ответному документу (response): по содержимому его поля $REF (оно содержит UNID документа-родителя) или свойством ParentDocumentUNID. ? Dim response As NotesDocument Dim parent As NotesDocument '...set value of response... Set parent = db.GetDocumentByUNID( response.GetltemValue( "$REF" )( 0 ) ) ' или Set parent = db. GetDocumentByUNID ( response. ParentDocumentUNID ) Пример 2. Java-агент для каждого ответного документа в базе находит родительский документ и выводит содержимое полей Subject обоих документов. Но обратите внимание, что как Java-агенты, так и скрипты, написанные в подобной манере - «коллекции документов и прямой выбор документов» -при большом количестве документов в базе характеризуются значительным временем исполнения. // Java-Database/getDocumentByUNID Database db = agent-Context. getCurrentDatabase ( ) ; DocumentCollection dc = db . getAHDocuments () ; Document doc, pdoc; © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: ©-формулы, LotusScript, встроенные классы LotusScript и Java String docSubj, pdocSubj; for (int. i = 0; i < dc. getCount () ; i + f) { doc = dc.getNthDocument(i+1); if (doc.isResponse()} { pdoc = db . getDocumentByUNID (doc . getParentDocument.UNTD () ) ; docSubj = doc.getltemValueString("Subject"); pdocSubj = pdoc.getltemValueString("Subject"); System, out .println ( "V" + pdocSubj + "\" has the response \"" + docSubj + "\>r") • } } 437 . Метод getDocumentByURL - «получить документ по URL из базы Web Navigator» . • ....•'..•' LotusScript: Set notesDocument ~ m>/esDa/aЈ>a.ve.getDocumentBylJRL( url$ [, reload ] [, urllist ] [, charsetS ] [, webuser$ ] [, \vebpasswd$ ] [ ,proxyuser$ ] [, proxypasswd$ ] [, nowait} ) Java: Document doc — Database.geiDocumeniByU'RL(String url, boolean reload) Document doc = Database.getDocumeniByURl^String url, boolean reload, boolean relifmod, boolean urllist, String charset, String webuser. String webpasswd, String proxymer, Stringproxypasswd, boolean nowait) Объект класса [Notes]Database, к которому применяется метод, должен представлять «серверную» или персональную базу Web Navigator. Метод возвращает объект класса [NotesjDocument, представляющий документ из этой базы и соответствующий указанному вами универсальному указателю ресурса (URL). Параметр url (тип String) - универсальный указатель ресурса (URL), например, "http://www.iotus.com". Длина строки не должна превышать 15 Кб. В LotusScript необязательный параметр reload имеет тип Integer. Значение 1 указывает на то, что необходимо «перезагрузить» гипертекстовую страницу с Web-сервера. Это «заставит» серверную задачу WEB или станцию соединиться с тем Web-сервером, на котором находится запрошенная страница, получить страницу, преобразовать ее в формат документа Notes, т.е. создать документ-образ, поместить документ-образ в базу Web Navigator, и только после этого создать объект класса NotesDocument, представляющий соответствующий странице документ из базы. Значение 2 «требует перезагружать» страницу с Web-сервера только тогда, когда она была модифицирована на Web-сервере по отношению к уже имеющемуся в базе Web Navigator ее документу-образу, или когда документа-образа еще нет в базе. Значение О или отсутствие параметра указывает на то, что не требуется выполнять перезагрузку страницы с Web-сервера. Если образ этой страницы уже имеется в базе Web Navigator, для него будет создан объект класса NotesDocument. Если же образа запрошенной страницы в базе Web Navigator нет, страница будет получена с Web-сервера, в базе Web Navigator будет создан ее документ-образ и возвращен представляющий его объект класса NotesDocument. В Java аналогичный эффект достигается двумя параметрами типа boolean. Если параметр reload равен true, то необходимо всегда перезагружать страницу с Web-сервера, если false -загружать страницу с Web-сервера нужно только тогда, когда ее документа-образа еще нет в базе. Однако параметр relifmod позволяет уточнить поведение, когда reload = false. Если relifmod -- true, то страницу требуется загружать, когда ее документа-образа нет в базе, а так же перезагружать тогда, когда она была модифицирована па Web-сервере по отношению к © InterTrust Со. Тел, (095) 9567928 Встроенные классы LotusScript u Java 438 уже имеющемуся в базе ее документу-образу. Если же relifmod = false, то страницу требуется загружать только тогда, когда ее документа-образа нет в базе. Запрошенная вами HTML-страница обычно содержит ссылки (URL) на другие страницы. Можно получить список всех ссылок страницы в отдельном поле документа-образа этой страницы. Естественно, выбор возможности ухудшает производительность, но любителям создавать «роботов» («пауков», «странников»...) - приложения, автоматически, обычно рекурсивно, получающих HTML-страницы с Web-серверов - эта возможность может пригодиться. Параметр urllist имеет в LotusScript тип Integer (по умолчанию 0), а в Java - тип boolean (в методе с двумя параметрами предполагается false). Значение I/true указывает на то, что все URL-ссылки (если есть) с этой страницы должны сохраняться в документе-образе страницы в текстовых полях с именами URLLinksn, а О/false - что не должны. Если возможность выбрана, «первое» поле со списком ссылок имеет имя URLLinksl. Если ссылок много, и их общий размер превышает 64 Кб, автоматически создается поле с именем URLLinks2, содержащее логическое продолжение списка, и т.д. Параметр char.set (тип String) за/дает кодировку, использованную на странице. Значение по умолчанию ""/null - задача WEB или клиент автоматически распознает кодировку страницы по ее MIME-атрибутам, а при их отсутствии в соответствии со своими настройками. Указывать кодировку явно, например, "ISO-8859-5", имеет смысл только тогда, когда кодировка неправильно опознается автоматически. Web-сервер, с которого должна быть получена страница, может требовать вашей аутентификации. Параметры webuser и webpasswd (оба типа String, по умолчанию ""/null) позволяют сообщить имя и пароль для доступа к Web-серверу. Задача WEB или станция клиента может иметь доступ в Internet через proxy-сервер, требующий аутентификации вводом имени и пароля. Параметры proxyuser и proxypasswd (оба типа String, по умолчанию ""/null) позволяют сообщить имя и пароль для доступа к proxy-серверу. . Последний параметр nowait, если задать его равным true, обеспечит «асинхронный возврат» из метода еще до того, как операция «скачивания страницы» завершится. Однако в этом случае вы не получите объекта [NotesJDocument - будет возвращено null. Значение же по умолчанию равно false - метод завершается «синхронно» и возвращает объект [NotesJDocument. Метод getURLHeadeflhfo - «получить HTTP/1.0 header fields для страницы» LotusScript: header$ = notc'sDatabase.geiUWLMenderlnfo(url$ , headername$ . Java: .. [, webuser$ ] [, webpasswd$ ] [ ,proxyuser$ } [, proxypass\vd$ ] ) String header = Database.getUKLHeaderInfQ(Strmg url, String headername, String webuser, String webpasswd, Siring proxyuser, String proxypasswd) Объект класса [NotesJDatabase, к которому применяется метод, должен представлять «серверную» базу Web Navigator. Метод позволяет получить значения полей (HTTP/1.0 header fields) страницы, заданной универсальным указателем ресурса url Имеются в виду значения полей, упомянутых в разделе 10 документа RFC 1945 «Hypertext Transfer Protocol HTTP/1.0», например, Content-Encoding, Content-Type, Content-Length, Date, Last-Modified, Server и др. Чтобы получить значение header, нужно указать название поля - headername. Символы «тире» в названиях полей должны быть предварительно заменены на символы подчеркивания, но с версии 5.0 это выполняется автоматически. Все параметры метода и возвращаемое значение типа String. Параметры, за исключением headername, точно такие же, как в методе getDocumentByURL. Если название поля или URL не найдены, возвращается ""/null. , . . . . . . © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 439 Пример. Скорее некоторая «загадочность», чем практическая ценность метода вынуждают привести пример его использования. Так, приведенный ниже скрипт вывел в диалоговых окнах следующее: Content-Encoding = Content-Type = text/html;charset=WlNDOWS-1251 Content-Length = 5969 Date= 18.12.98 13:57:59 GMT (текущий момент времени) Last-Modified = (действительно отсутствовал для этой страницы) Server = Lotus-Domino/Release-4.6.2 Dim db As NotesDataba.se • Set db = New NotesDatabase("","") Dim URL, hn As String . '•• URL = "http://www.inttrust.ru" . If db.openURLDb() Then Print db.Title hn = "Content Encoding" MsgBox (hn & " ' = " & db.getURLHeade.rInfo{tTRL,hn) ) hn = "Content_Type" MsgBox (hn & " --= " & db. getURLHeaderlnfо (URL,hn) ) hn — "Content_Length" MsgBox (hn & " =- " & db. getURLHeaderlnf о (URL, hn) ) hn = "Date" MsgBox <hn & " - " & db.getURLHeaderlnfо(URL, hn) } hn = "Last Modified" MsgBox (hn & " = " & db.getURLHeaderlnfо(URL,hn)} hn = "Server" MsgBox (hn & " = " & db.getURLHeaderlnfо(URL,hn)) End If Метод getP^offleDocument - «создать или получить профильный документ» LotusScript: Set notesDocument = notesDatabase,geiProuleBocument( profileName$ [, userName$ ] ) Java: Document profileDoc = Database,getProfi\eDocument(StringprqfileName, String userName) «Профильные» документы (profile documents) предоставляют быстрый, простой и эффективный способ сохранения в базе и последующего извлечения из нее всевозможных данных, относящихся как ко многим пользователям, так и к конкретному пользователю. В отличие от обычных документов, профильные документы не отображаются в видах базы и не учитываются при подсчете количества документов в базе. Профильный документ всегда имеет имя и может быть извлечен из базы по этому имени. Для более удобного доступа к такому документу может быть изготовлена форма, имя или алиас которой должны в точности совпадать с именем профильного документа. Тогда «по команде» @Command([EditPro(ile} ; formName) можно «перевести» этот документ в режим редактирования. Имя профильного документа можно рассматривать как «первичный ключ» для доступа к нему. Профильные документы только с «первичным ключом» обычно используются для хранения данных, относящихся ко многим пользователям. При необходимости обеспечить для каждого пользователя свой уникальный профильный документ в качестве «вторичного ключа» используется имя пользователя в «каноническом» формате. К такому документу возможен доступ «командой» @Cornmand([EditProfile] ; formName ; userName), где formName задает имя профильного документа и одновременно является именем или алиасом формы, используемой для доступа к такому документу, a userName - имя пользователя, задающее конкретный документ. © InterTrust Со. Тел. (095) 9567928 440 Встроенные классы LotusScript и Java Отметим, что в профильном документе всегда присутствует поле с предопределенным именем $Name, содержащее, как показывают эксперименты, информацию либо вида «$profile_NNN__/brwA'a/K&_» (например, "Sprofile 008protllel_"), если это «не привязанный к пользователю» документ, или информацию вида «Sprofile NNN_formName_userName» (например, "$profile_008profilel_cn=nikolay n. ipntsev/o=intertrustcorp/c=su"), если документ «привязан к пользователю», а так же поле SNoPurge, означающее, что этот документ не подлежит удалению. Рассматриваемый метод возвращает объект класса [Notes]Document, представляющий профильный документ с именем profileName (тип String) и относящийся к пользователю userName (тип String). Если профильный документ с именем profileName для пользователя userName существует, возвращаемый объект класса [Notes]Document представляет этот документ, и вам становится доступна информация из его полей. Если же такой документ отсутствует, то метод создает объект класса [Notes]Document для «нового» документа, и вы можете создать в нем необходимые поля, а затем сохранить этот документ, применив к нему метод save. Когда вы указываете в качестве параметра userName пустую строку, имеется в виду профильный документ, не относящийся ни к какому пользователю». Пример 1. Скрипт получает доступ к профильному документу с именем "Interest Profile" для текущего пользователя, а затем получает и выводит информацию из полей этого документа. Предполагается, что поля документа содержат списки значений, поэтому значительная часть кода относится в извлечению и форматированию выводимой информации. Dim session As New NotesSession Dim db As NotesDatabase Dim doc As NotesDocument Dim profileAuthors As Notesltem Dim. profileStrings As Notesltem Dim stringAuthors As String Dim stringStrings As String Set db = session.CurrentDatabase Set doc = db.GetProfileDocument{"Interest Profile", session.UserName) Set profileAuthors = doc.GetFirstltem("ProfileAuthors"} Set profileStrings - doc.GetFirstltem("ProfileStrings") stringAuthors - "" stringStrings =•• "" Forall profileAuthor In profileAuthors.Values stringAuthors = stringAuthors & Chr(lO) SprofileAuthor End Forall Forall profileString In profileStrings.Values stringStrings -- stringStrings & Chr(lO) &profileString End Forall If stringAuthors = "" Then stringAuthors = "None" •; Else • " stringAuthors -- Right(stringAuthors, Len(stringAuthors) - 1) End If If stringStrings = "" Then stringAuthors r= "None" Else stringStrings = Right(stringStrings, Len(stringStrings) - 1) End If Messagebox stringAuthors,, "Profile authors" Messagebox stringStrings,, "Profile strings" Пример 2. Java-агент получает доступ к профильному документу с именем "Author Profile" для текущего пользователя, а затем получает и выводит информацию из полей этого документа. // Java-Database/getProfileDocument © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 441 Database db = agentContext.getCurrentDatabase(}; Document doc = db.getProfileDocument("Author Profile", session.getUserNameО); String who =: doc . getItemValueString ( "Who" } ; String email - doc.getltemValueString("Email"); String phone = doc.getItemValueString ( "Phone"); System.out.println("Who: " + who); System.out.println("Email: " + email); System.out.println("Phone: " + phone); © Метод getProfileDocColIection - «получить коллекцию профильных документовбазы». . " : . . ' .' .:. ..: : . . . . . . . . . . ' . ' . . . . . ••.'...." : LotusScript: : Set notesDocumentCollection = notesDatabase.getProTilcDocCottection( [proftleName$] ) Java: DocumenlCollection dc - Da/a^as't'-getProfileDocColiectionC Siring profileName) Возвращает объект класса [NotesJDocumentCoIlection, представляющий коллекцию (возможно, пустую) из профильных документов с именем profileName (тип String), т.е. «созданных по форме» profileName. Если параметр profileName опущен в LotusScript или задан равным null в Java, возвращается коллекция из всех профильных документов базы. Пример. Java-агент демонстрирует цикл для получения всех профильных документов с именем "Author Profile". / / J av a - Da t ab as e /g e tP ro fil e Do cCo l l ec t ion Database db = agentContext.getCurrentDatabase( } ; DocumentCollection dc = db.getProfileDocColIection("Author Profile"); Document: doc - dc . getFirstDocument (} ; while (doc !- null) { System.out.println(doc.getItemValueString("Who")); doc = dc.getNextDocument(}; } 3.5.8. Методы для получения элементов дизайна Метод getAgent - «получить агента» LotusScript: Set notesAgent = notes Database.get Agent( agentName$ ) Java: Agent agent = Database.getAgent(String agentName) По заданному имени агента возвращает объект, представляющий этот агент из базы, к которой применяется метод. Пример 1. Скрипт выводит в окне список имен агентов базы, получает от пользователя имя агента для запуска и запускает этого агента. Dim session As New NotesSession Dim db As NotesDatabase Dim theAgent As NotesAgent Dim agentString As String Set db = session.CurrentDatabase Forall agent In db.Agents agentString = agentString & Chr(lO) & End Forall agent.Name ' . © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 442 Messagebox agent-String,, "Agents" Set theAgent = db.GetAgent(Inputbox("Which agent do you want to run?")) If Not(theAgent Is Nothing) Then Call theAgent.. Run Else Messagebox "No existing agent selected" End If Пример 2, Java-агент получает агента с именем My Agent и выводит некоторые его свойства. / / J a va -D at a ba s e / g etA g e nt Database db ™ agentContext.getCurrentDatabase ( ) ; Agent agent = db.getAgent("My Agent"); System.out.printIn("Agent:\t" + agent.getName()); System.out.println("Owner:\t" + agent.getOwner( ) ) ; System.out.println("Last run:\t" + agent.getLastRun( } ) ; System, out .print .In ( "Query: \t" + agent. getQuery ( ) ) ; Метод getView - «получить вид или панку» . . . . LotusScript: Set notesView ~ notesDatabase.getVie\v( viewName$ ) Java: View view ~ Database*getVK\v(Sl:ring viewNanie) По заданному имени вида или папки возвращает объект, представляющий этот вид или папку из базы, к которой применяется метод. Параметр viewName (тип String) - имя вида или папки в базе - не чувствителен к регистру. Это должно быть или полное имя вида или папки (включая обратный слеш для «каскадных» имен) или алиас (синоним), но не оба вместе. Например, для вида "MaimBy Author | AuthorView" можно указать либо "MainVBy Author", либо "AuthorView". Символ подчеркивания в именах видов или папок, используемый для выбора клавиши-акселератора, можно как включать в задаваемое имя, так и не включать. Если он включен в имя, метод работает немного быстрее. Возвращаемое значение - объект класса [NotesJView, представляющий вид или папку. Если база расположена на сервере, метод может вернуть только общий вид или папку. Если же база локальна, метод может вернуть как общий, так и личный вид или папку, который хранится не в базе, а в файле DESKTOP.DSK на компьютере пользователя. Пример 1. Скрипт получает вид Main View в текущей базе и выводит в окне имя вица. Dim session As New NotesSession Dim db As NotesDatabase Dim view As NotesView Set db - session.CurrentDatabase Set view = db.GetView( "Main View" Messagebox{ view.Name } ,, . ) Пример 2. Java-агент получает вид ($А11) в текущей базе и выводит и выводит количество колонок в нем. // Java-Database/getDocumentByUNID Database db = agentContext.getCurrentDatabase ( ) ; View view = db.getView("($A11)" ) ; System.out.println("($A11) has " + view.getColumns( ) . size() + " columns"); Метод getForm - «получить форму» LotusScript: Set notesForm = notesDatabase.geiForm(formName$ ) © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Java: 443 Form form - Database.getForm(StringformName) По заданному имени формы возвращает объект, представляющий эту форму из базы, к которой применяется метод. Параметр formName (тип String) - или полное имя формы (включая обратный слеш для «каскадных» имен) или алиас (синоним), но не оба вместе. Возвращаемое значение - объект класса [Notes]Form, представляющий форму. Пример. Скрипт проверяет, существует ли в текущей базе форма, имя или алиас которой вводятся в диалоговом окне. Dun session As New NotesSession Dim db As NotesDatabase Dim form As NotesForm On Error Goto processError Set. db --= session. CurrentDatabase formNameln = Inputbox ("Name of form1?") Set form = db.GetForm(formNameln) Messagebox "The form """ & form.Name & """ exists" Exit Sub processError: REM If Err () = ErrObjectVariableNotSet Then If Err() =• 91 Then Messagebox "The form """ & formNameln & """ does not exist" Else Messagebox "Error " & Err() & ": " & Error() End If . Exit Sub © Метод getOutline - «получить существующую Outline» LotusScript: Set notesOiitline = notesDatabase.getOutlme(outlinename$) Java: Outline outline = Database.getQutlim(String outlineName) Возвращает объект класса [NotesjOutline, представляющий существующую в базе Outline (как элемент дизайна) с именем outlineName (тип String). @ Метод createOutliiie - «создать новую Outline» LotusScript: Set notesOutline ~ notesDatabase.createOuUme(outlinename$ [, defaultOutline}) Java: Outline outline — Database,ci*eateQutline(Slririg outlineName) Outline outline = Database.createOutline(String outlineName, boolean defaultOutline) Создает в базе новую Outline (как элемент дизайна) и возвращает объект класса [NotesjOutline, представляющий этот элемент дизайна. Параметр outlineName (тип String) задает название для создаваемой Outline. Однако если в базе уже существует Outline с таким названием, то объект [NotesjOutline будет представлять этот существующий элемент дизайна. Если параметр defaultOutline равен false (по умолчанию), то создается «пустая» Outline, если true - создается Outline с элементами по умолчанию. Остальные подробности даются в описании классов [NotesjOutline и [NotesjOutlineEntry. Встроенные классы LotusScript и Java 444 @ Метод enabkFoIder - «создать папку, если ее нет» LotusScript: Call notesDatabase.enahleҐolder(folderName$ ) Java: void Database.eaableFolder(String folderName) Проверяет, существует ли в базе папка с именем folder Name. При отсутствии создает новую папку с таким именем. 3.5.9. Методы для управления доступом к базе Метод query Access - «получить уровень доступа» LotusScript: Java: /eve/% = notesDatabase.queryA,cce$s( nameS ) int level = Datcjbase.queryAccess(String name) Возвращает уровень доступа субъекта с именем пате (тип String) к данной базе. Субъект может быть пользователем, группой или сервером. Имя субъекта может как присутствовать, так и отсутствовать в списке управления доступом (ACL) базы. Возвращаемое значение level * константа типа Integer/int, ее возможные значения: « ACLLEVEL _NOACCESS / ACL.LEVEL_NOACCESS - нет доступа, * ACLLEVEL DEPOSITOR / ACL.LEVEL_DEPOSITOR - депозитор, * ACLLEVEL_READER / ACL.LEVEL_READER - читатель, * ACLLEVEL, AUTHOR / ACL.LEVEL_AUTHOR - автор, » ACLLEVEL EDITOR / ACL.LEVEL_EDITOR - редактор, * ACLLEVEL DESIGNER / ACL.LEVEL_DESIGNER - дизайнер, * ACLLEVEL^ MANAGER / ACL.LEVEL ^MANAGER - менеджер. Если имя субъекта иерархическое, должно быть указано полное имя в формате [Canonicalize], например "CN=Vladimir A. Panov/O=InterTrustCorp/C=SU", или [Abbreviate], например "Vladimir A. Panov/lnterTrustCorp/SU", Если указанное имя субъекта явно присутствует в ACL базы, возвращается уровень доступа субъекта. Если указанное имя субъекта отсутствует в ACL базы явным образом, метод выполняет следующее: * * * если субъект является членом группы, а название этой группы присутствует в АСЕ базы, метод возвращает уровень доступа группы; если субъект является членом нескольких групп из ACL базы, метод возвращает наибольший уровень доступа среди этих групп; если субъект не является членом ни одной из групп в ACL базы, метод возвращает уровень доступа «любого прочего» (-Default-) к этой базе. Состав групп всегда определяется методом по основной адресной книге компьютера, на котором происходит выполнение. Пример 1. Скрипт определяет уровень доступа пользователя с именем Vladimir A. Panov/lnterTrustCorp/SU к базе CHECK.NSF. Dim db As NotesDatabase Dim level. As Integer Set db = New NotesDatabase( "NotesSrv400/InterTrustCorp/SU", "check.nsf"~ ) level = db.QueryAccess( "Vladimir A. Panov/lnterTrustCorp/SU" ) Если в ACL базы явно указано, что Vladimir A. Panov/lnterTrustCorp/SU имеет доступ автора, независимо от того, в какие группы он входит, возвращается ACLLEVEL AUTHOR. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 445 Если Vladimir A. Panov/InterTrustCorp/SU член группы, которая имеет доступ дизайнера к базе, но сам Vladimir A. Panov/InterTrustCorp/SU не указан явно в ACL базы, возвращается ACLLEVEL_DESIGNER. Если Vladimir A. Panov/lnterTrustCorp/SU член одной группы, имеющей доступ редактора к базе, и одновременно член другой группы, имеющей доступ дизайнера к базе, но сам Vladimir A. Panov/InterTrustCorp/SU не указан явно в ACL базы, возвращается ACLLEVEL_DESIGNER. Если Vladimir A. Panov/lnterTrustCorp/SU не указан явно в ACL базы и не является членом ни одной группы в ACL базы, а для -Default- в ACL базы указан доступ читателя, возвращается ACLLEVEL READER. Пример 2. Java-агент определяет уровень доступа текущего пользователя к текущей базе. // Java-Database/queryAccess Database db = agentContext.getCurrentDatabase(); String title = db.getTitle(); int accLevel = db,queryAccess(session.getUserName( ) ) ; System, out .print {"E'or database \ " " + title + "\" you have " ) ; switch (accLevel) i case(ACL.LEVEL_NOACCESS} case(ACL.LEVEL_DEPOSITOR) case(ACL.LEVEL_READER) case(ACL.LEVEL^AUTHOR) case(ACL.LEVEL_EDITOR) case(ACL.LEVEL_DESIGNER) case(ACL.LEVEL_MANAGER) default } System.out.println (" System.out.print("no"); System.out.print("depositor"); System.out.print("reader"); System.out.print("author"); System.out.print("editor"); System.out.print("designer"); S y s te m . o u t . p r in t ( " m a n a g e r " }; System.out.print("unknown"); break ; break; break ; break; break ; break ; break; break; access"); Метод grantAccess - «предоставить уровень доступа» LotusScript: Call notesDatabase.grantA.ccess( name$ , /eve/% ) Java: void Database,grantAcce$s(String name, int level) - Изменяет список управления доступом (ACL) базы так, что заданному имени пате (пользователю, серверу или группе) предоставляется заданный уровень доступа level. Если заданное имя уже присутствует в ACL базы, изменяется только уровень доступа, иначе заданное имя добавляется в ACL базы с заданным уровнем доступа, Параметр пате типа String, a level - константа типа Integer/int, возможные значения которой такие же, как в методе queryAccess. Пример 1. Скрипт предоставляет к базе всем из группы Sales Supervisors доступ автора, a Sam Sidorov/Acme/RU - доступ менеджера. Dim db As New NotesDatabase{ "Serverl/Acme/RU", "profits.nsf" db.GrantAccess( "Sales Supervisors", ACLLEVEL_AUTHOR ) Call db.GrantAccess{ "Sam Sidorov/Acme/RU", ACLLEVEL_MANAGER ) ) Call Пример 2. Java-агент предоставляет к базе доступ менеджера всем серверам данного домена и доступ читателя всем серверам из других доменов, //' Java-Database/queryAccess Database db = agentContext.getCurrentDatabase(); db.grantAccess("LocalDomainServers", ACL.LEVEL__MANAGER); db.grantAccess("OtherDomainServers", ACL.LEVEL_JREADER); © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 446 Метод revokeAccess - «удалить из ACL базы» . .••• LotusScript: Call notesDa(abase.revokeA.ccess( name.$ ) Java: void Database.revokeAcces$(Strmg name) Удаляет имя пользователя, группы или сервера, заданное параметром пате (тип String) из списка управления доступом (ACL) базы. Применение метода revoke отличается от присвоения методом grantAccess доступа ACLLEVEL NOACCESS / ACL.LEVEL NOACCESS. Метод revoke просто удаляет имя субъекта из ACL, но этот субъект eaie может иметь к базе доступ как -Default- или как член группы. Когда лее метод grantAccess «явно» присваивает имени субъекта уровень доступа NOACCESS, субъект безусловно не будет иметь доступа к базе, независимо от установок для -Default- и его «вхождения» в группы. Если имя пате отсутствует в ACL, в LotusScript возникает ошибка, а в Java генерируется исключение "The name is not in the list". Пример. Скрипт лишает Willi Hacker/Acme права пользования базой. Сначала скрипт удаляет имя Willi Hacker/Acme из ACL, «стремясь не засорять АС1. лишними именами». Но затем проверяет, сохранил ли после этого Willi Hacker/Acme какой-нибудь доступ к базе. Если все-таки сохранил (как -Default- или член группы), то скрипт вновь обеспечивает явное присутствие в ACL имени Willi Hacker/Acme с уровнем доступа No Access. Dim user As String user = "Willi Hacker/Acme" Him db As New NotesDatabase( "Serverl/Acme/RU", "profits.nsf" ) Call db.RevokeAccess( user ) If ( db.QueryAccess( user ) <> ACLLEVEL_NOACCESS ) Then Call db.GrantAccess( user , ACLLEVEL_NOACCESS } End If 3.5.10. Методы полнотекстового поиска и «обычного» поиска документов Метод FTSearch - «полнотекстовый поиск по базе» LotusScript: Set notesDocumentCollection ~ notesDatabase.ҐTSearch( queryS, moxDocs% I, sortoptions [, otheroptions}}) Java: . DocumentCollection dc -••- Databose.ҐTSearcb(String query) DocumenlCollection dc — Dalabasc.FTSearch(Sfring query, bit maxDocs) DocumentCollection dc = Database.FTSe&rch(String query, inf maxDocs, in! sortoptions, int otheroptions) Выполняет запрос полнотекстового поиска по всем документам в базе. Параметр query (тип String) задает запрос полнотекстового поиска. Параметр maxDocs (тип Integer/int) сообщает, что в качестве ответа на запрос должно возвращаться не более чем maxDocs документов. Чтобы возвращались все удовлетворяющие запросу документы, задайте 0. Параметр sortoptions (тип Integer/int) сообщает порядок, в котором должна быть отсортирована полученная коллекция документов: F1 SCORES/Database.FT_SCORES (по умолчанию) - по убыванию показателя соответствия поисковому запросу, FT_DATE_DES/Database.FT_DATE_DES - по убыванию времени создания документов («более свежие в начале»), FT_DATE ASC/Database.FT DATE_ASC - по возрастанию времени создания документов («более свежие в конце»). © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 447 Параметр otheroptions (тип Integer/int) задает дополнительные опции поиска: FT_STEMS/Database.FT_STEMS - выполнять поиск так же по синонимам слов из запроса, FT_FUZZY/Database.FT FUZZY - выполнять поиск так же по «однокоренным» словам из запроса, FT_DATABASE/Database.FT_DATABASE - выполнять поиск в базах Domino, FT_FILESYSTEM/Database.FT_FILESYSTEM - выполнять поиск в файлах, не являющихся базами Domino. Возможен выбор нескольких опций, например, FT STEMS + FT FUZZY, a значение 0 трактуется как отсутствие дополнительных опций. Возвращаемое значение представляет собой коллекцию документов (объект класса [Notes]DocumentCollection), удовлетворяющих запросу. Если ничего не найдено, в возвращаемой коллекции будет 0 элементов. Коллекция соответствующим образом отсортирована. Если она отсортирована по убыванию значения показателя соответствия поисковому запросу, то получить значение показателя для любого документа из коллекции можно свойством FTSearchScore класса [Notes]Document. Метод работает, даже если база не имеет индекса полнотекстового поиска, однако значительно менее эффективно. Для проверки наличия индекса полнотекстового поиска используют свойство IsFTIndexed, а для создания индекса - метод updateFTIndex. Для поиска не по всем документам в базе, а только по документам из заданного вида используют одноименный метод класса [NotesJView. Для поиска же по предварительно отобранной коллекции документов используют метод FTSearch класса [Notes]DocumentCollection. Если база, к которой применяется метод, имеет индекс полнотекстового поиска по многим базам (имеется в виду база типа Multi DB Search, а не база, имеющая «установленное» свойство MultiDbSearch), то в коллекции найденных документов могут содержаться документы из разных баз. Пример. Скрипт присылает Joann Smera/Medical обзорный документ, содержащий ссылки (DocLink-и) на все документы из базы invntion.nsf на сервере Berlin/Medical, которые были обнаружены полнотекстовым поиском. Запрос полнотекстового поиска требует, чтобы документ содержал слово "vaccine" (вакцина). Отбирается не более 10 документов. Если база не имеет индекса полнотекстового поиска, запрос не выполняется. Dim db As New NotesDatabase( "Berlin/Medical", "invntion.nsf" ) Dim collection As NotesDocumentCollection Dim newsletter As NotesNewsletter Dim doc As NotesDocument If db.IsFTIndexed Then Set collection = db. FTSearch { "vaccine-", 10 ) Set newsletter = New NotesNewsletter( collection ) Set doc = newsletter.FormatMsgWithDoclinks( db ) ' doc.Form = "Memo" doc.Subject = "Here's the newsletter you requested." Call doc.Send( False, "Joann Smera/Medical" ) End If . , . . ; . . Пример 2. Java-агент выполняет запрос полнотекстового поиска по текущей базе и выводит количество обнаруженных документов. // J a va -D a ta b a se / FT S e a rch Database db = agentContext.getCurrentDatabase(); String title -= db . getTitle ( ) ; String qry = ""; if (db.isFTIndexed()) { // He более .10 документов со словом "vaccine" /I qry = "vaccine"; // DocumentCollection dc = db.FTSearch(qry, 10); // He более 100 документов со словами "red" и "blue" // qry = "red & blue"; © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 448 I/ DocumentCollection dc = db.FTSearch("red & blue", 100); //' He более 100 документов со словами "red" и "blue" и сортировкой // найденных документов по убыванию даты создания qry = "red & blue"; DocumentCollection dc = db.FTSearch(qry, 100,' Database.FT_DATE_DES, 0); int matches = dc.getCount (); System.out.println("FTSearch of \"" + title + "\" found " + matches + " document, (s) with " + qry); } e 1se Syst em. out .pr int ln ( " Data bas e V " + ti tle + "\" is not full text indexed"); Метод unprocessedFTSearch - «полнотекстовый поиск по необработанным агентом документам» . .. . . . . . . . . . ...^ LotusScript: Set notesDocitmentCollection = notesDataha$e.nnprocesse<lҐTSearcli( queryS, maxDocs% [, sortoptions [, otheroptions\\) Java: DocumentCollection dc = AgentContext.unprocessedFTSearcb( String query, int maxDocs) DocumentCollection dc = AgentContext.nnprocessedҐTSeai ch( String query, int maxDocs, int sortoptions, int otheroptions) Для заданного запроса полнотекстового поиска возвращает коллекцию документов, которые еще не обработаны текущим агентом (unprocessed) и удовлетворяют запросу полнотекстового поиска. Все параметры и возвращаемое значение такие же, как в методе FTSearch. В LotusScript этот метод может применяться только в скриптах агентов и действий по виду (view actions), и только при условии, что объект класса NotesDatabase получен свойством CurrentDatabase из объекта класса NotesSession. Если метод пытаются применять в ином контексте, получают пустую коллекцию. Если метод пытаются применять к объекту, полученному не свойством CurrentDatabase из объекта класса NotesSession, получают сообщение об ошибке. Вероятно, именно в целях более четкого определения контекста применения подобных методов в Java введен класс AgentContext, членом которого и является одноименный метод в Java. Метод работает в два приема: • • Во-первых, находит коллекцию документов, еще не обработанных данным агентом. Эта коллекция зависит от типа агента. Она идентична коллекции, получаемой свойст вом UnprocessedDocuments класса NotesDatabase/AgentContext. Во-вторых, выполняет запрос полнотекстового поиска по коллекции необработанных документов и возвращает полученную в результате коллекцию удовлетворяющих запросу. Если база не имев! индекса полнотекстового поиска, метод работает, но значительно менее эффективно. Пример. В Agent Builder выбрано, что Java-агент обрабатывает все или только «отмеченные» документы в виде. Агент отбирает документы со словом "botany" и помещает их в папку "Botanist's Delight". // Java-Database/unprocessedFTSearch DocumentCollection dc = agentContext.unprocessedFTSearch("botany", Database.FT_SCORES, Database.FT__STEMS+Database.FT_THESAURUS); © InterTrust Co. Тел- (095) 9567928 0, Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 449 Document doc; . int. size = dc . getCount () ; System, out. println { "Count =- " + size); for (int i = 1; i <= size; i++) i doc = dc.getNthDocument( i ) ; doc.putInFolder("Botanist's Delight"); System.out.println(i + " *** " + doc.getltemValue("Subject" } ) ; } Метод search - «поиск с формулой отбора по документам базы» LotusScript: Set notesDocumentCollection = notesDatabase.searcb( formula^, notesDateTime, maxDocs% ) Java: DocumentCollection dc =-- Database.se&rch(Slring formula) DocumentCollection dc =- Database.search(String formula, DateTime df) DocumentCollection dc ~ Database.se&rch(String formula, DateTime dt, int maxDocs) Возвращает коллекцию документов, удовлетворяющих заданному формулой критерию отбора. Параметр formula (тип String) - @-формула Notes с применением @функций, определяющая критерий отбора документов. Параметр notesDateTime/dt - объект класса [Notes]DateTime, задающий «момент отсечки» (cutoff date) - тогда метод просматривает в базе только документы, созданные или модифицированные не ранее данного момента времени. Чтобы «момент отсечки» вообще не принимался во внимание, задайте параметр равным Nothing/null. Параметр maxDocs (тип Integer/int) - максимальное количество документов, которое вы хотите получить в коллекции. Чтобы получать все отобранные документы, задайте 0. Возвращаемое значение - объект класса [NotesjDocumentCoilection - несортированная коллекция документов, удовлетворяющих заданному критерию. Формула отбора вычисляется для каждого документа в базе, созданного или модифицированного не ранее указанного «момента отсечки». Если формула возвращает @Тше, считается, что документ удовлетворяет критерию отбора. Пример 1. Скрипт отбирает в базе все ответные документы (формула отбора - @lsResponseDoc), созданные или модифицированные после 1 декабря 1998 года. Dim db As New NotesDatabase( "Serverl/Acme", "somedocs.nsf" ) Dim collection As NotesDocumentCollection Dim dateTime As New NotesDateTime( "12/01/98" ) Set collection = db.Search( "@IsResponseDoc", dateTime, 0 ) Пример 2. Java-агент отбирает в базе все документы, в поле Subject которых содержится текст, который агент выбирает из своего коля комментариев, // Java-Database/unprocessedFTSearch Agent, agent = agentContext.getCurrentAgent( ) ; Database db = agentContext.getCurrentDatabase( ) ; S t ri n g t i t l e = db.getTitle(); DocuznentCollection dc = db.search("Subject= \""+agent.getComment ()+"\""); int matches = dc . getCount. ( } ; System.out.println("Search of \"" + title + "\" found " + matches + " document( s ) with Subject = \"" + agent.getComment(} + " \ " " ) ; Пример З. Поле ReminderDate («дата напоминания») в каждом документе формы Project служит для хранения даты, когда «напоминание» должно быть отправлено. Агент на LotusScript, используя © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Javd 450 метод search, отбирает документы формы Project, в которых «дата напоминания» равна отправляет напоминание почтой и «сдвигает дату» в поле ReminderDate на неделю вперед. текущей, Dim db As New NotesDatabase ( "", "reminder:. nsf" ) Dim collection As NotesDocumentCollection Dim doc As NotesDocument Dim dateTime As New NotesDateTime( "12/01/98" ) Dim nextDateTime As NotesDateTime searchFormula$ = "Form = ""Project"" & ReminderDate = @Today" Set collection = db.Search( searchFormula$, dateTime, 0 ) ' Create a date that's one week from today. ' That's when the project participants get their next reminder. Set nextDateTime = New NotesDateTime( "Today" } Call nextDateTime.AdjustDay( 7 ) ' E'or each document with reminder date today, send document, to ' project participants. ' Then update the Reminder-Date field with a date ' one week from today. For i = 1 To collection.Count Set: doc - collection. GetNthDocument ( i ) Call doc.Send( True ) Call doc.ReplaceltemValue( "ReminderDate", nextDateTime.LSLocalTime ) Call doc.Save( True, False ) Next Метод unprocessedSearch - «поиск с формулой отбора по необработанным агентом документам» . . ..... . : . / . . . : , ' . • . ••;•• ::.: • :: • -'••'. LotusScript: Set notesDocumentCollection = notesDatabase,unprocessedScarch( formiila$, notes DateTime, maxDocs% ) Java: DocumentCoUection dc L= AgentContext.u.nprocessedSearch( String for mulct) DateTime dt, int maxDocs) Для заданных формулы отбора и момента отсечки возвращает коллекцию документов из базы, которые еще не обработаны данным агентом (unprocessed), удовлетворяют формуле отбора и созданы или модифицированы после момента отсечки (cutoff date). Все параметры и возвращаемое значение такие же, как в методе search. Метод работает в два приема: * * Во-первых, находит коллекцию документов, еще не обработанных данным агентом. Эта коллекция зависит от типа агента. Она идентична коллекции, получаемой свойством UnprocessedDocuments класса NotesDatabase/AgentContext. Во-вторых, он выполняет по коллекции необработанных документов отбор документов, созданных или модифицированных после момента отсечки и удовлетворяющих формуле отбора, и возвращает полученную в результате коллекцию. Метод unprocessedSearch класса NotesDatabase может применяться только в агентах и действиях по виду (view actions), и при условии, что объект класса NotesDatabase получен свойством CurrentDatabase из объекта NotesSession. Если метод пытаются применять не в агентах, получают пустую коллекцию. Если метод пытаются применять к объекту, полученному не свойством CurrentDatabase из объекта NotesSession, возникает ошибка. Вероятно, именно в целях более четкого определения контекста применения этого и ему подобных методов в Java и был введен класс AgentContext. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 451 Пример. Пусть в «построителе агентов» выбрано, что данный Java-агент обрабатывает только выбранные пользователем документы в виде. В этом случае свойство UnprocessedDoeuments возвращает коллекцию этих (выбранных пользователем) документов. Агент отбирает из них документы, созданные после 1 января 1998 года и содержащие слово "botany" в поле Subject. Отобранные документы помешаются в папку "Botanist's Delight". // Java-Database/unprocessedSearch DateTime date = session.createDateTime("01/01/98"); DocumentColleetion dc = agentContext.unprocessedSearch( "SContains(Subject; \"botany\")", date, 0); Document doc; int size = dc.getCount(); System.out.println("Count = " + size); for (int i = 1; i <= size; i+4) { doc = dc.getNthDocament(i); doc.putlnFolder("Botanist's Delight"); System.out.println(i + " *** " + doc.getltemValue("Subject")!; i © Метод FTDomainSearch - «иолнетекстовый поиск по базам домена» LotusScript: Set notesDocument = note5Dcrra&ave.FTDomainSearch( query , maxDocs% [, sortoption% ] [, otheroptions% ] [, start& j [, count% ] , entryForm ) Java: Document searchResDoc - Dfltoftoi re.FTDomainSearch(^rwg query, int maxDocs, int sortoptions, int oiheroptions, int start, int count, String entryForm) Объект класса [Notes]Database, к которому применяется метод, должен представлять базу Domain Catalog. Метод осуществляет полнотекстовый поиск документов по всем базам домена, которые перечислены в базе Domain Catalog и имеют свойство MultiDbSearch. Параметр query (тип String) задает запрос полнотекстового поиска. Параметр maxDocs (тип Integer/int) сообщает, что в качестве ответа на запрос должно возвращаться не более чем maxDocs документов. Чтобы возвращались все удовлетворяющие запросу докумен ты, задайте 0. Параметр start (тип Long/int) сообщает номер первой возвращаемой страницы, а параметр count (тип Integer/int) - количество возвращаемых страниц. Параметр entryForm (тип String) дает имя поисковой формы в базе Domain Catalog, например, "Search Form" или "DomainQuery". Остальные параметры - sortoptions и otheroptions - такие же, как в методе FTSearch. Возвращается объект класса [Notes]Document, представляющий документ с результатами выполнения поискового запроса - «ссылками» на найденные по запросу документы в базах домена. 3.5.11. Методы для выполнения административных действий с базами Метод compact - «уплотнить локальную базу» LotusScript: sizeDelta& ~ notesDatabase.compact Java: int sizeDelta - Database.compactQ «Уплотняет» локальную базу. Возвращает разницу в байтах (тип Long/int) размеров базы до и после уплотнения. Для баз, находящихся на сервере, выдает ошибку или генерирует © InterTrust Со. Тел. (095) 9567928 Встроенные классы LotusScript и Java 452 исключение. Не может использоваться и для уплотнения текущей базы (которая содержит этот скрипт или Java-агент, использующий метод compact). Пример. Java-агент уплотняет базу данных, имя файла которой он получает из своего поля комментариев, если в этой базе реально используется менее 75% пространства. // Java-Database/сompact Agent agent = agentContext.getCurrentAgent(); String dbNarne = agent . get Comment ( ) ; Database db = session.getDatabase(null, dbName); String title = db.getTitle ( ); double percentUsed = db.getPercentUsed(); if (percentUsed < 75) { System, out. println ( "Compacting database \"" + title -f " \ " " ) ; int saved == db. compact () ; } System.out.println("Database \"" + title + "\" is " + (int}percentUsed + " percent used"); i Метод updateFTIndex - «обновить индекс полнотекстового поиска» LotusScript: Call notesDatabase,upda.teVTInde\( createf'lag ) Java: void Database.updateҐTlnden(boolean createFlag) Обновляет индекс полнотекстового поиска базы. Параметр createf'lag можно задать равным true только для локальных баз - это означает, что когда индекс полнотекстового поиска у базы не существует, метод должен создавать этот индекс. В противном случае задавайте false, поскольку при попытке создать индекс полнотекстового поиска в базе на сервере возникает' ошибка или генерируется исключение. Метод replicate - «выполнить репликацию локальной базы» •LotusScript: Java: , .... flag ~- notes Database,replicate( serverName$ ) boolean flag ~ Database.replicate(String serverName) Выполняет репликацию локальной базы, к которой применяется метод, с ее ренликой(ами) на сервере, имя которого задано параметром serverName. В репликации примут участие все реплики данной базы на указанном сервере. Если в процессе репликации не возникло ошибок, возвращается true, иначе false. Если на сервере нет реплики данной базы или база, к которой применяется метод, не локальна, возникает ошибка или генерируется исключениеМетод remove - «удалить базу» ; . . ; • ... • . :• •... ... • . . . . . . - . LotusScript: Call notesDatabase.remove Java: void Database.remo\eQ . Удаляет базу, связанную с объектом, с диска. Пример. Скрипт удаляет базу BYEBYE.NSF, если она не изменялась за последние 100 дней. Dire db As New NotesDatabase( "", "byebye.nsf" ) If { ( Today - db.LastModifled ) > 100 ) Then Call db.Remove End If • ' • © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 453 3.6. «Репликационные установки» - класс flNotesjReplication Свойства объекта класса [NotesJReplication позволяют определять и устанавливать ряд свойств базы данных, касающихся поведения базы данных при репликациях. Методы объекта этого класса позволяют «считывать» репликационные установки базы данных в объект, «заносить» репликационные установки из объекта в базу данных, а так же выполнять «очистку» истории репликаций базы. Получают ссылку на объект класса [NotesJReplication свойством Replicationlnfo класса [NotesJDatabase. В каждом объекте [Notes]Database содержится только один объект [NotesJReplication. LotusScript: Java: . •- ••.-. , . NolesReplication = notesDatabase*Rep\Kationlnfo Replication ri — Database.geiReplicatianlnfoQ 3.6.1. Свойства © Свойство Abstract - «принимать «полные» или «усеченные» документы» LotusScript: flagBoolean - NotesReplication,Abstract NotesRepIication.Abstract -flagBoolean Java: boolean flag — ReplicationAsAbstrstctQ void Replication.setAbstr»ct(boolean flag) При репликации в данную реплику базы могут приниматься или «полные», или «усеченные» (truncated) документы. «Усеченный» документ может появиться в реплике базы, если в ее репликационных установках выбрана возможность Receive summary and 40KB of rich text only (Рис. 3.15). В «усеченном» документе по сравнению с «полным» сохранена информация в полях с флагами Summary, но размер информации в полях типа RichText и полях иных типов с флагами Non-Summary не превышает примерно 40 Кб, а все присоединенные файлы и OLE-объекты «отброшены». Если свойство Abstract равно true, в реплику принимаются «усеченные» документы, если false - «полные». Рис. 3.15 Окно репликационных установок базы на закладке Space Savers © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 454 © Свойство Cutofflnterva! - «интервал устаревания документов» LotusScript: intervalLong — NotesReplication.Cutofnnterval NofesReplicaliori.Cuiofflnterval = intervalLong Java: long interval = Replicatwn.getCutofflntervAlQ void Replication.setCutofflntervAl(long interval) Интервал устаревания документов в данной реплике базы. Задается количеством дней (тип Long/long). В окне репликационных установок базы интервал устаревания указывается в поле XXX возможности Remove documents not modified in the last XXX days (Рис. 3.15), причем вне зависимости or того, выбрана или нет сама эта возможность. Документы, с момента последней модификации которых уже прошло заданное свойством количество дней, подлежат автоматическому удалению из данной реплики базы, только если в ее репликационных установках была выбрана возможность Remove documents not modified in the last XXX days. При этом удаляемый документ заменяется своим «окурком». «Окурки», с момента появления (иными словами, последней модификации) которых уже прошло заданное свойством количество дней, безусловно подлежат «полному» удалению из данной реплики базы. © Свойство CutoffDelete - «разрешено ли автоматически удалять устаревшие : 'документы» " . : . .'.• "•' : :•: :-:'^' .• : • ' " ' • • ' . . ' . л ". •••' ; LotusScript: flagBoolecm = NotesReplication.CutoffDelete NotesReplication.CutoffDelete = flagBoolean Java: boolean flag = Replication.isCutoffDeleteO void Rep!ication.setCutoffDe\ete(boolean flag) Свойство соответствует возможности Remove documents not modified in the last XXX days в репликационных установках базы. Значение true разрешает, a false - запрещает автоматически удалять из данной реплики базы документы, с момента посл едней модификации которых уже прошло заданное свойством Cutofflnterval количество дней. _ © Свойство CutoffDate - «порог времени для приема документов при репликации» ; ''•-. " .-. '••- ' • . . , . ; • .. '-..-.. •'•'::,•....;:":••.- ••:••-.-•"";. :: •••'• -: LotusScript: Java: timeDate Variant = NotesReplication.CutoffD'Ate DateTime timeDate = RepIication.getCutoffDateQ Возвращает дата-временное значение: в LotusScript Variant of type DATE, в Java - объект класса DateTime. Документы, время последней модификации которых меньше CutoffDate, при репликации в данную реплики базы не принимаются. В документации Domino версии 5.0 утверждается, что это значение, получаемое вычитанием из значения текущих даты-времени интервала устаревания документов (Cutofflnterval). Однако практика показывает, что свойство просто возвращает значение из поля Only replicate incoming documents saved or modified after в репликационных установках базы (Рис. 3.17). Значение в этом поле всегда может быть произвольным образом изменено «вручную», однако затем оно эпизодически подвергается автоматическим корректировкам, получая при них значения, «достаточно близкие» к тем, которые получаются вычитанием интервала устаревания документов (Cutofflnterva!) из значения текущих даты-времени. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (ар-формулы, LotusScript, встроенные классы LotusScript и Java 455 © Свойство Disabled - «участвует ли в репликациях» LotusScript: flagBoolean - NotesReplication.Disabled No(esReplication.Disabled =flagBoolean Java: boolean flag - RepIication.isDisabletlQ void Replication,seil)isabled(boo!ean flag) Значение true разрешает, a false - запрещает участие данной реплики в репликациях. В окне репликационных установок базы это свойство соответствует возможности Temporarily disable replication (Рис. 3.17), Puc. 3.16 Окно репликационных установок базы на закладке Send Puc. 3.17 Окно репликационных установок базы на закладке Other 0 Свойство IgnoreDelctes - «передаются ли «окурки» из данной реплики в другие» .'" -;•; :Г.. •'"".•'.'.: ' •• ''•'•"• : ' ' ' . -; " - '.-... •-:-'•'••:•••';" .'--;';; •'•'../•;•";;./'•:: ;:;..'-. .', ;;-:'::'. '-•:-• LotusScript: flag = NotesReplication.IgnoreDeletes © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 456 NotesReplication. Igno reDeletes = flag boolean flag = Replication.islgnoreDeletesQ void Java: Repiication,seiIgnoreDe:letes(boolean flag) Значение true запрещает, a false разрешает при репликациях передачу «окурков» из данной реплики в другие реплики. В окне репликационных установок базы это свойство соответствует возможности Do not send deletions made in this replica to other replicas (Рис. 3.16). @ Свойство IgnoreDestDeletes - «принимаются ли «окурки» в данную реплику из других» LotusScript: flagBoolean = NotesReplication. IgnoreDestDeletes NotesReplication.lgnoreDestDeletes -flagBoolean Java: boolean flag = Replication.islgooreDesiDeletesQ void Replication.setIgnoreDestDeietes(&o0/eo77 flag) Значение true запрещает, a false разрешает при репликациях прием «окурков» в данную реплику из других реплик. В окне репликационных установок базы это свойство соответствует возможности Deletions (Рис. 3.18). ixl Replication Settings for Глоссарий Wher»Јomputef: Receive* trom: pomino500/lnterTtus(Corp/SLI I -A nv Server- Space Saveiv Send Other ' Advanced ' "* "'1 JSJJ ~ ""M*w* д-п И1П III «if Г" ^ AIIDociirnents _ 1 Без описания _ I Все по термину оригинала __ J По риссв.пмчтррмину Replicate П7 Forms, views etc P* Acces., F? ,4дзп^ P f fieleliotu ori fotniuio Г Fjelds j ^ O K J Lint f'nc. 3.18 Окно репликационных установок базы на закладке Advanced @ Свойство Priority - «приоритетность участия в реплкациях» LotusScript: constantLong = NotesReplication.friority NotesReplication.Priority = constantLong Java: int. constant - Replication.geiPriorityQ void Replica(ion.setPriority(int constant) ! 1риоритетность участия в репликациях для данной реплики, задается константами: DB REPLICATION,PRIORITY HIGH/ RepHcation.CNOTES_REPLCONST_PRIORITYHIGH - высокая, © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (а)-формулы, LotusScript, встроенные классы LotusScript и Java * DB_ REPLICATION PRIOR1TY_MED/ Replication.CNOTES_REPLCONST_PRIORITYMED - средняя, * DB_REPLICATION_PRIORITY_LOW/ Replication.CNOTES_REPLCONST_PRIORITYLOW - низкая, DB_REPLICATION_PRIORITY_NOTSET/ Replicalion.CNOTESJREPLCONST JPRIOR1TYNOTSEТ - не выбрана. * 451 Приоритетность может быть учтена администратором при составлении расписания репликаций баз. 3.6.2. Методы © Метод clearHistory - «очистить историю репликаций» LotusScript: Call NotesReplication.cle-Arflistory Java: int returnValue = Replication.clearVListoryQ Очищает историю репликаций базы. © Метод reset - «занести репликационные установки базы в объект» LotusScript: Call NotesReplication.reset Java: int returnValue = Replication.resetQ Заносит репликационные установки базы данных в объект [NotesjReplication. © Метод save - «занести репликационные установки из объекта в базу» LotusScript: Call NotesReplication.s«ve Java: int returnValue = Replication.saveQ Записывает репликационные установки из объекта в базу данных. Без вызова этого метода до закрытия базы свойства, измененные Вами в объекте, не будут записаны в саму базу данных, и, соответственно, не начнут функционировать. Пример 1. Следующий скрипт проверяет работоспособность всех свойств и методов класса NotesReplication. Dim bt As Long tot = 36 ' MB_YESNO + MB_ICONQUESTION Dim IDDK As Integer IDDK = 6 ' Ok Dim db As NotesDatabase Dim rep As NotesReplication Set db = session.CurrentDatabase Set rep = db.Replicationlnfo ' Abstract If Messagebox(rep.Abstract,bt,"Change Abstract?") = IDDK Then rep.Abstract = Not rep.Abstract End If , ' CutOffInterval If Messagebox(rep.CutOffInterval,bt,"Change CutOffInterval?") = IDDK Then rep.CutOffInterval = rqp.CutOffInterval + 1 End If © InterTrust Co. Тел. (095) 9567928 458 Встроенные классы LotusScript и Java CutOffDate Msgbox rep.CutOffDate,,"CutOffDate" 1 CutoffDelete If Messagebox(rep.CutoffDelete,bt, "Change CutoffDelete?"} - 1DOK Then rep.CutoffDelete = Not rep.CutoffDelete ' . End If ' Disabled If Messagebox(rep.Disabled,bt,"Change Disabled?") = IDOK Then rep.Disabled = Not rep.Disabled End If ' IgnoreDeletes If Messagebox(rep.IgnoreDeletes,bt,"Change IgnoreDeletes?") = IDOK Then rep.Ign.oreDelet.es == Not rep. IgnoreDeletes End If ' Priority Select Case rep.Priority Case DB_REPLICATION PRIORITY HIGH: If Messagebox("PRIORITY_HIGH",bt,"Change Priority (LOW)?") - IDOK Then rep.Priority = DB_REPLICATION_PRIORITY LOW End If Case DB_REPLICATION_PRIORITY_MED: If Messagebox("PRIORITY_MED",bt,"Change Priority (HIGH)?") = IDOK Then rep.Priority = DB REPLICATION^PRIORITY_HIGH End If Case DB_REPLICATION_PRIORITY_LOW: If Messagebox("PRIORITY_LOW",bt,"Change Priority(MED)?") - IDOK Then rep. Priority = DB_REPLICATION_PRIORITY__MED End If Case DB REPLICATION^PRIORITY NOT/SET: If Messagebox("PRIORITY_NOTSET",bt,"Change Priority?") = IDOK Then rep.Priority = DB_REPLICATION_PRIORITY_LOW End If End Select ' IgnoreDestDelet.es If Messagebox(rep.IgnoreDestDeletes,bt,"Change IgnDestDel?") = IDOK Then rep.IgnoreDestDeletes = Not rep.IgnoreDestDeletes End If 1 clearHistory () •, If Messagebox("",bt,"clearHistory()?") = IDOK Then Call rep.clearHistoryО End If ' reset() OR save() If Messagebox("",bt,"save()?") = IDOK Then Call rep.save{) Else Call rep.reset() End If 1 Пример 2. Java-агент, подобно скрипту из предыдущего примера, демонстрирует работу свойств и методов класса Replication. // Java-Replication-All Database db =; agentContext.getCurrentDatabase(); Replication rep = db.getReplicationlnfо(); // Abstract rep.setAbstract(!rep.isAbstract()); System, out. println ( "Abstract. = " + rep.isAbstract ()); // Cutofflnterval rep.setCutoffInterval(rep.getCutoffInterval() + 1); © InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 459 System.out.println("CutoffInterval = " + rep,getCutoffInterval()); // CutoffDate System.out.println{"CutoffDate = " + rep.getCutoffDate()); // CutoffDelete rep.setCutoffDelete(!rep.isCutoffDelete()); System.out.println("CutoffDelete - " + rep.isCutoffDelete()); // Disabled rep.setDisabled(!rep.isDisabled()); System.out.println("Disabled = " + rep.isDisabled()); // IgnoreDeletes rep.setlgnoreDeletes(!rep,isIgnoreDeletes()); System, out . pr.int.ln ( "IgnoreDeletes = " 4 rep . isIgnoreDeletes ()); // Priority switch (rep. getPriority () ) .• /,-. ,.-..••-- .,-., ..•;,•>• •,-,-..;•'•"*•:;.--, . .• :- ' : ;. { case Replication.CNOTES REPLCONST_PRIORITYHIGH: // В 5.0 нет Replication.DB REPLICATION PRIORITY_HIGH . . . rep.setPriority(Replication.CNOTESJREPLCONSTJPRIORITYLOW) ; System.out.println("Priority ~ HIGH->LOW"); break; c a s e R e p l i ca t i o n .C N O T E S R E PL C O N S T_ P R 1 0 RI T Y M E D : r e p. s e t P ri o r i t y( R e p l i c at i o n . CN O T E S __ R E P L C O NS T _ P R IO R I T Y HI G H ) ; System.out.println("Priority = MED->HIGH"); break; c a s e R e pl i c a t io n . C N OT E S _ R E P LC O N S T _P R I O R IT Y L O W : rep.setPriority(Replica tion.CNOTES_REPLCONST PRIORITYMED) ; System.out.println("Priority = LOW->MED"); break; c a s e R e p l i ca t i o n .C N O T E S R E P L CO N S T P R IO R I T Y NO T S E T : rep.setPriority(Replication.CNOTES_REPLCONST_PRIORITYLOW) ; System.out.println("Priority = NOTSET->LOW"); break; i /'/ IgnoreDestDeletes rep.setlgnoreDestDeletes(!rep.isIgnoreDestDeletes()); System.out.println("IgnoreDestDeletes = " + rep.isIgnoreDestDeletes()); // clearHistory() rep.clearHistory(); System.out.println("clearHistory!"}; // reset () OR save () System.out.print In("reset () OR save() !"); rep.save(); // rep.reset(); При своем выполнении агент выводит приблизительно следующее. Первое выполнение Второе выполнение Abstract = true Abstract = false Cutofflnterval = 127 CutoffInterval = 128 CutoffDate = 20.01.9802:34:22 ZE3 CutoffDate = 20.01.98 02:34:22 ZE3 CutoffDelete = true CutoffDelete = false Disabled -= true Disabled = false IgnoreDeletes = false IgnoreDeletes = true Priority - HIGH->LOW Priority = LOW->MED IgnoreDestDeletes = false IgnoreDestDeletes = true clearHistory! clearHistory! reset () OR save()! reset () OR save ( } ! © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 460 3.7. «Список управления доступом» - класс [NotesJACL Объект этого класса представляет список управления доступом (ACL) базы. ACL включает две компоненты: • список элементов ACL, каждый из которых содержит имя владельца элемента ACL (пользователя, сервера или группы), его тип и уровень доступа к базе, а так же дополнительные свойства; список ролей вместе с назначением владельцев элементов ACL на роли. * • Access Control List PeopI?, Sewras, flumps- Show AH \sf* 4 , Щ| •»] User type: -Default- &eeess Unspecified И ReaJei ^| A Nuolay N Iontsev.5nterTrustCorp/SU >— _ j^ NotesSrHOMnteiTnistCorpCl) r ' 3U OtheiDonainServ«rc '_ Авторы ' Иван И Иванов/ЛсмЯШ Г" С иак wtuivjij.ia^-s agents Редакторы Г* ' Сидор Г Сидаров/ACME/RU Г" gnte раЫас dacijeants Roles [Mam Developer] »J [Очень дп] 1 Remmf j ^ [Роль!] Rales — — - — — • — ™— __«___. — i -_ kd ... Last cbuvp • Kikol «fN Iotttsevun2909P3 Accoittagto Intel TnistCarpjOSU Us . i Add. | genare, —J K jp^,^ jj ^j f f QK 1 Cancel I i ---- S",, ,., t ------- !L, — i .. ! .J Рис. 3.19 Список управления доступом базы, закчадка Basics Свойства и методы этого класса позволяют получать «общие свойства ACL»: максимальный уровень доступа к базе через Internet, поддержку в одинаковом состоянии ACL во всех репликах базы, а так же список ролей из ACL, переименовывать, добавлять новые или удалять роли, получать доступ к существующим элементам ACL (по имени владельца или последовательным просмотром всех элементов) и создавать новые и удалять существующие элементы ACL. «Контейнерная иерархия» LotusScript Java NotesDatabase — >, Database > NotesACL — > NotesACLEntry NotesDatabase ACL -» ACLEntry Database Для получения объекта класса [NotesJACL используют свойство ACL класса [NotesjDataba.se. Кроме того, в классе [NotesJDatabase имеются три метода - queryAccess, grantAccess и revokeAccess - которыми можно осуществлять доступ к ACL базы, не создавая при этом явно объекта класса [Notes]ACL. Работа же с элементами ACL осуществляется методами и свойствами класса [NotesJACLEntry. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (аи-формулы, LotusScript, встроенные классы LotusScript и Java 461 Пример 1. Скрипт получает доступ к ACL базы, а затем к ее первому элементу. Dim Dim Dim Set Set db As New NotesDatabase( "", "names.nsf" ) acl As NotesACL entry As NotesACLEntry acl = db.ACL entry = acl.GetFirstEntry Пример 2. Java-агент получает доступ к ACL текущей базы, а затем к первому элементу ACL. // Java-ACL/getACL Database db ™ aqentContext.getCurrentDatabase(); ACL acl = db.getACLC); .,., ACLEntry entry •= acl. getFirst.Entry () ; 3.7.1. Свойства Свойство Parent- «родитель» • : . . . , . -•• ... . . . . . • : : • . • , . -v.;: . ........... .-•... LotusScript: Set notesDatabase — notesACL.Psurent Java: Database db = ACL.getParentQ База данных, ACL которой представляет объект класса [NotesjACL. Пример 1. Скрипт в обоих окнах выведет одно и тоже название локальной базы N AMES.NSF. Dim db As New NotesDatabase( " ", Dim parentDb As NotesDatabase Dim acl As NotesACL Set acl = db.ACL "names.nsf" ) Set parentDb - acl.Parent Messagebox ( db.Title } Messagebox{ parentDb.Title ) Пример 2. Подобно предыдущему примеру, Java-агент дважды выведет название текущей базы. // Java-ACL/ParentAgent Database db = agentContext.getCurrentDatabase(); ACL acl = db.getACL(); Database parent = acl.getParent(); System.out .println ("Database is \"" +• db. getTitle () •+ "\""); System.out.println ("Parent database is \"" + parent.getTitle (} + "\""); Свойство Roles-«роли»•'-•" "•'••;"•'v;"::::.':••'••/.:."':;;'::::;••;"'.-:•'•'' ""-•'-":• -•-::"':,>:"; "::•.:-.•••-' ••:;:'".".' LotusScript: stringArray = notesACLRtA&s Java: java.util Vector roles ;= /JCZ/.getRolesQ Возвращает «массив» названий ролей (в LotusScript тип Array of strings, в Java -java.util.Vector с элементами типа String), определенных в ACL. Каждый элемент массива -название роли, заключенное в квадратные скобки, например, "[Supervisor]". Но для чего здесь квадратные скобки? Чтобы было возможным отличить роли от привилегий (анахронизм Notes версии 2.0) - названия привилегий заключались в круглые скобки. Пример 1. Скрипт выводит все роли, определенные в ACL, текущей базы. Например, он мог бы вывести "[HR Contact]", "[Supervisor]" и "[Project Leader]". Dim session As New NotesSession Dim db As NotesDatabase © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 462 Dim aci As NotesACL Set db = session.CurrentDatabase Set acl =• db.ACL Forall r In acl.Roles Messagebox( r } End Forall Puc. 3.20 Список управления доступом базы, закладка Roles Пример 2. Агент выводит все роли, определенные в ACL текущей базы. i m po rt J ava .u ti l . Ve ct o r ; // Java-ACL/RolesAgent Database db = agentCoritext. getCurreritDatabase () ; ACL acl = db.getACLO ; Vector roles = acl.getRoles(}; for (int i=0; i < roles.size( ) ; i++) System.out.printIn(roles.elementAt(i}); @ Свойство InternetLevel - «максимальный доступ к базе по протоколам : Internet прикладного уровня при аутентификации вводом имени и пароля» LotusScript: levellnteger = notesACL. InternetLevel notesACL. InternetLevel = levellnteger Java: int level = /JCL.getlnternetLevelQ void /lCL.setInternetL.evel(mt level) Максимальный уровень доступа к базе по протоколам Internet прикладного уровня (HTTP, РОРЗ, ШАР, NNTP) при аутентификации вводом имени и пароля (задается в поле Maximum Internet name & password, см. Рис. 3.2). Возможные уровни доступа задаются константами: ACLLEVEL_NOACCESS / ACL. LEVELING ACCESS - нет доступа, ACLLEVEL_DEPOSITOR/ ACL.LEVELlDEPOSITOR - депозитор, © InterTrust Co. Тел, (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 463 ACLLEVEL_READER / ACL.LEVEL READER - читатель, ACLLEVEL_AUTHOR / ACL.LEVELj\UTHOR - автор, ACLLEVEL_ED1TOR / ACL.LEVEL_EDITOR - редактор, ACLLEVEL_DESIGNER / ACL.LEVEL DESIGNER - дизайнер, ACLLEVELJMANAGER / ACL. LEVEL" MAN ACER - менеджер. Чтобы выполненные в объекте [Notes]ACL изменения были «записаны» в базу, для объекта необходимо вызвать метод save. • Рис. 3.2 Список управления доступом базы, закладка Advanced Пример 1. Скрипт выводит заданный в ACL текущей базы максимальный уровень доступа к этой базе по протоколам прикладного уровня Internet при аутентификации вводом имени и пароля, а затем изменяет его на ACLLEVEL READER. Dim session As New NotesSession Dim db As NotesDatabase Dim acl As NotesACL Dim lev As Integer Set db = session.CurrentDatabase Set acl = db.ACL lev = acl.InternetLevel If lev = ACLLEVEL_NOACCESS Then Print If lev = ACLLEVEL_DEPOSITOR Then Print If lev - ACLLEVEL_READER Then Print If lev = ACLLEVEL_AUTHOR Then Print If lev = ACLLEVEL_EDITOR Then Print If lev = ACLLEVEL^DESIGNER Then Print If lev - ACLLEVEL MANAGER Then Print acl. InternetLevel "= ACLLEVEL_READER Call acl.save lev; lev; lev; lev; lev; lev; lev; " " " " " " " NOACCESS" DEPOSITOR" READER" AUTHOR" EDITOR" DESIGNER" MANAGER" Пример 2. Агент выводит заданный в ACL текущей базы максимальный уровень доступа к этой базе по протоколам прикладного уровня Internet при аутентификации вводом имени и пароля, а затем изменяет его на ACL.LEVEL MANAGER. //Java-ACL/InternetLevelAgent Database db =• agentContext. getCurrentDatabase () ; ^InterTrustCo. Ten. (095) 9567928 Встроенные классы LotusScript и Java 464 ACL acl = db.get.ACL () ; int level =-• acl.getlnternetLevel(); String strLevel = "UNDEE'INED" ; if (level == ACL.LEVEL_NOACCESS) strLevel = "NOACCESS"; if (level == ACL.LEVEL_DEPOSTTOR) strLevel = "DEPOSITOR"; if (level == ACL.LEVEL^READER) strLevel - "READER"; if (level == ACL.LEVEL_AUTHOR) strLevel = "AUTHOR"; if (level == ACL.LEVEL_EDITOR) strLevel, = "EDITOR"; if (level == ACL.LEVEL_DESIGNER) strLevel = "DESIGNER"; if (.level == ACL.LEVEL^MANAGER) strLevel -•= "MANAGER"; System, out. println ( "Maximum InternetLevel is-, " + level + " .-;.-- ; • •• ("+strLevel+")"); ' . acl.setlnternetLevel(ACL.LEVEL_MANAGER); acl.save(); Свойство UniformAccess - «должен яи поддерживаться одинаковый список управления доступом во всех репликах» ..... . .•- I LotusScript: flag - notes ACL, Uniform Access HotoJCZ.UniformAccess -flag Java: boolean flag = ^CX.isUniformAccessO voidyiCjL.setUniform\.cces$(boolean flag) Свойство определяет, должен ли список управления доступом поддерживаться в одинаковом состоянии во всех репликах этой базы и «функционировать» даже при локальном доступе к базе (задается в поле Enforce a consistent Access Control List across all replicas of this database, см. Рис. 3.2). Как в Java, так и в LotusScript true означает, что свойство установлено, a false - нет. Чтобы выполненные в объекте [Notes]ACL изменения были «записаны» в базу, для объекта необходимо вызвать метод save. Пример 1. Скрипт выдает в диалоговом окне текущее значение свойства UniformAccess и, если нажата кнопка Yes, изменяет значение свойства на «обратное». Const MB YESNO = 4 Const MB_ICONQUESTION = 32 Const IDYES - 6 Dim Dim Dim Set Set. ' Yes and No buttons ' Warning query ' Yes button pressed session As New NocesSession db As NotesDatabase acl As NotesACL db =- session. CurrentDatabase acl = db.ACL If acl.UniformAccess Then If Messagebox("Do you want to toggle?", MB YESNO + MB_ICONQUESTION, "Uniform access is in effect") = TDYES Then acl.UniformAccess = False Call acl.Save End If E1 я е If Messagebox("Do you want to toggle?", MB_YESNO + MB ICONQUESTION, "Uniform access is not in effect") - IDYES Then acl.UniformAccess = True Call acl.Save End If End If © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 465 Пример 2. Агент изменяет значение свойства Uniform Access на "обратное". // Java-ACL/UniforrnAccessAgent • Database db = agentContext.getCurrentDatabase(); ACL acl = db.getACLf); System.out.println("Uniform access is " + acl.isUniformAccess()); if(acl.isUniformAccess()) acl.setUniformAccess(false); eJ.se acl. setUnif ormAccess (true) ; acl.save(); System, out .println ( "Uniform access is " + acl. isUnif ormAccess ()); ' 3.7.2. Методы Метод addRole - «добавить роль» LotusScript: Call notes ACL.&ddRole( name$ ) Java: void ACL.^ddRole(String name) Добавляет в ACL роль с заданным названием (тип String). Название роли не нужно «заключать в квадратные скобки». Если указанная роль уже существует в ACL, в LotusScript произойдет ошибка, а в Java будет возбуждено исключение "The role name already exists". Чтобы изменения, выполненные в объекте, были «записаны» в саму базу, для объекта необходимо вызвать метод save. Пример 1. Скрипт добавляет в ACL роль Developer. Dim session As New NotesSession Dim db As NotesDa.taba.se Dim acl As NotesACL Set db == session. CurrentDatabase Set acl - db.ACL Call acl.AddRole( "Developer" ) Ca11 а с1,S a ve Пример 2, Агент добавляет в ACL роль, название которой записано в поле комментариев этого агента. // Java-ACL/AddRoleAgent Agent agent = agentContext.getCurrentAgent( ) ; Database db = agentContext. get.CurrentDatabase ( ) ; ACT, acl = db.getACL 0; acl.addRole(agent.getComment()); acl.save(); - Метод deleteRole - «удалить роль».... ,:. -; ,:.:. • -: •:...•;.:• . ...... •:•••,.•:•:. .... ,: :-•':::••'•:• LotusScript: Call notesACL.deleteRo\e( name$ ) Java: void ACL.deleteRolf:(Strmg name) Удаляет из ACL роль с заданным названием (тип String). Название роли не нужно «заключать в квадратные скобки». Если указанная роль отсутствует в ACL, в LotusScript произойдет ошибка, а в Java будет возбуждено исключение "Role name not found". Чтобы изменения, выполненные в объекте, были «записаны» в саму базу, для объекта необходимо вызвать метод save. © InterTrust Со. Тел. (095) 9567928 Встроенные классы LotusScript и Java 466 Mei од renameRole - «переименовать роль» LotusScript: Call notesAi X.renameRoIe( oldNameS, newNameS) Java: void ACL.renameRole(String oldName, Siring newName') Переименовывает роль oldName в newName (оба параметра типа String). Названия ролей не нужно «заключать в квадратные скобки». Все элементы ACL, ранее назначенные на роль oldName, станут назначенными на роль newName. Если старое название роли отсутствует в ACL, ничего не происходит. Чтобы изменения, выполненные в объекте, были «записаны» в саму базу, для объекта необходимо вызвать метод save. Пример 1. Скрипт переименовывает роль "Developer" в "Main Developer". Dim session As New NotesSession Dim db As NotesDatabase Dim acl As NotesACL Set db = session.CurrentDatabase Set acl = db.ACL Call acl.RenameRole( "Developer", "Main Developer" ) Caii aci.Save Пример 2. Агент добавляет суффикс "Role" к названию каждой имеющейся в ACL роли. Например, [Supervisor] будет заменено на [SupervisorRole]. Каждая строка из вектора ролей содержит название роли «в квадратных скобках». Названия ролей передается методу renameRole «без квадратных скобок». import j ava.util.Vector; // Java-ACL/RenameRoleAgent Database db = agentContext.getCurrentDatabase(); ACL acl = db.getACL(); Vector roles = acl.getRoles(}; String role; for (int. i = 0; i < roles. size (); i+-+) { role =• (String) roles . elementAt (i ); role = role.substring (1, role.length()-1); acl.renameRole((String)roles.elementAt(i), role + "Role"); } acl.save(); Метод getEntry - «получить элемент ACL но его имени» .•:,:•• • -..• ..LotusScript: Set notesACLEntry - notesACL.geiEntry( nameS ) Java: ACLEntry entry =ACL.getEntry(String name) : .. .... ... По имени элемента ACL (пользователя, сервера или группы), заданному параметром пате (тип String), возвращает объект класса [NotesjACLEntry, представляющий этот элемент ACL. Должно быть указано полное имя в формате [Canonicalize] или [Abbreviate], причем с учетом регистра. Если элемент пате не найден в ACL, в LotusScript возвращается Nothing, а в Java - null. Если вам требуется определить уровень доступа к базе некоторого субъекта, который не указан в ACL явно, но имеет к базе доступ как член группы, метод getEntry не поможет -используйте для этого метод queryAccess класса [Notes]Database. О InterTrust Co. Тел. (095) 9567'92'8 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 467 Пример 1. Скрипт получает элемент для Nikoiay N. lontsev/InterTrustCorp/SU из ACL текущей базы. Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase Dim acl As NotesACL Dim entry As NotesACLEntry Set acl = db.ACL Dim ename As String ename = "CN=Nikolay N. lontsev/O=InterTrustCorp/C=SU" '[Canonicalize] ename = "Nikoiay N. lontsev/InterTrustCorp/SU" '[Abbreviate] Set entry = acl.GetEntry(ename) If entry Is Nothing Then Print: ename & " not found" Else Print entry.Name & " found" End If Пример 2. Если агент находит в ACL текущей базы элемент с именем, которое указано в поле комментариев этого агента, он выводит сообщение о способности владельца элемента ACL удалять документы. Если не находит, то выводит сообщение об отсутствии элемента ACL для заданного имени. // Java-ACL/GetEntryAgent Agent agent = agentContext.getCurrentAgent( ) ; Database db = agentContext.getCurrentDatabase(); ACL acl = db.getACL( ) ; ACLEntry entry = acl.getEntry(agent.getComment()); if (entry != null) { if (entry.isCanDeleteDocuments()) System, out .println (entry. getNarne () + " can delete documents"}; else System.out.println (entry.getName() + " cannot delete documents"); } else System.out.println ("No entry for " + agent.getComment()); Метод getFirstEntry - «получить первый элемент ACL».:• • - :•.••;....•..::. . •••• . . ...... LotusScript: Set notesACLEntry = notesACL.geiFirstEntry Java: ACLEntry entry = ACLEntry /4CLgetFirstEntry() Возвращает объект класса [NotesJACLEntry, представляющий первый элемент в ACL базы. Обычно это элемент для "-Default-". Метод getNextEntry - «получить следующий за указанным элемент ACL» LotusScript: Set notesACLEntry - notes ACL.geiNextEntry (notesACLEntry) Java: ACLEntry entry = /ICX.getNexiEntryO ACLEntry entry = ACL.gGtNen.tEntry(ACLEntrypreventry) Возвращает объект класса [NotesJACLEntry, представляющий элемент из ACL ба:^ы, следующий за элементом, заданным параметром метода, или, если в Java был применен метод без параметров, ранее извлеченным из объекта ACL элементом. Если следующего элемента нет, в LotusScript возвращается Nothing, а в Java - null. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 468 Пример 1. Скрипт выводит имена всех элементов из ACL текущей базы. Dim session As New NotesSession Dim db As NotesDatabase Set db = session.CurrentDatabase Dim acl As NotesACL ... Dim entry As NotesACLEntry Sot aci ~ db.ACL Set entry = acl.GetFirstEntry While Not entry Is Nothing P r in t e ntry.N ame Set entry = acl.GetNextEntry(entry) Wend Пример 2. Агент проверяет, содержится ли имя, указанное в поле комментариев этого агента, в ACL текущей базы. Имя должно задаваться в формате [Caninicalize], но без учета регистра. // Java-ACL/GetFirstEntryAgent •' Agent agent = agentContext.getCurrentAgent(); Database db = agentContext.getCurrentDatabase(); ACL acl = db.getACL(); boolean gotlt = false; ACLEntry entry = acl.getFirstEntry(); do { if ( entry . get Name () . equals IgnoreCase (agent. . get Comment ( ) ) ) { gotlt = true; break; } } while ( (entry = acl.getNextEntry(entry)) != null); if (gotlt) System., out .print In (entry . getName () -h " is in the ACL"); else System.out.print In(agent,getComment() + " is not in the ACL"); 1 Метод create ACLEntry - «создать элемент ACL» . "•' . ••.•:...,..;.. • ............. . .... ••• . . LotusScript: Java: Set notesACLEntry — «0to/4CZ,.createACLEntry( name$, level% ) ACLEntry entry = ACL,createACljE,ntry(String name, int level) Создает в ACL новый элемент с именем пате (тип String) и уровнем доступа level. Уровень доступа задается одной из следующих констант: ACLLEVELJMOACCESS / ACL.LEVEL_NOACCESS - нет доступа, ' ACLLEVEL!DEPOSITOR / ACL.LEVEL DEPOSITOR - депозитор, ACLLEVEL READER / ACL.LEVELJIEADER - читатель, ACL.LEVEL_ AUTHOR / ACL.LEVEL_AUTHOR - автор, ACLLEVEL EDITOR / ACL.LEVEL_EDITOR - редактор, ACLLEVEL~DES1GNER / ACL.LEVELJDES1GNER - дизайнер, ACLLEVELlMANAGER / ACL.LEVEL_MANAGER - менеджер. Метод возвращает объект класса [Notes] ACLEntry, представляющий созданный элемент. Не забывайте вызывать метод save для сохранения модифицированной ACL в базе. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 469 Пример !. Скрипт добавляет группу Редакторы с доступом редактора в ACL текущей базы. Dim session As New NotesSession . . Dim db As NotesDatabase Set db = session.CurrentDatabase Dim acl As NotesACL Dim entry As NotesACLEntry Set acl = db.ACL . . Set entry = acl.CreateACLEntry { "Редакторы", ACLLEVEL_EDITOR ) Call acl.Save Пример 2. Агент добавляет имя, указанное в поле комментариев этого агента, в ACL текущей базы с доступом автора. // Java-ACL/CreateACLEntryAgent Agent agent = aqentContext.getCurrentAgent(); Database db = agentContext.getCurrentDatabase () ; ACL acl - db.get.ACLO ; acl. CreateACLEntry (agent. getComment. () , ACL. LEVEL_AUTHOR) ; acl.save(); © Метод removeACLEntry - «удалить элемент ACL»' . : •..•.-••••••••Java: .......::;:' void ACL.remove\CLEntry(String name} Удаляет из ACL элемент с именем пате (тип String). He забывайте вызывать метод save для сохранения модифицированной ACL в базе. Пример 1. Агент удаляет имя. указанное в поле комментариев этого агента, из ACL текущей базы. // ACL/RemoveAclEntry Agent agent = agentContext.getCurrentAgent ( ) ; Database db = agentContext.getCurrentDatabase( ) ; ACL acl = db.getACL(); acl.removeACLEntry(agent.getComment()); acl.save() ; Метод save - «сохранить информацию из объекта ACL в базе» LotusScript: Call notesACL.$a\e Java: public void ACL.saveQ Сохраняет выполненные в объекте класса [NotesjACLEntry изменения в базе (в файле базы на диске). Без вызова этого метода до закрытия базы все выполненные в объекте изменения будут утеряны. Встроенные классы LotusScript и Java 470 3.8. «Элемент из списка управления доступом» - класс [NotesJACLEntry Представляет один элемент (для пользователя, сервера или группы) из списка управления доступом (ACL) базы. Свойства и методы этого класса позволяют определять и изменять имя владельца элемента ACL, его уровень доступа, тип и дополнительные возможности (может ли удалять документы, создавать новые документы, папки, агентов и пр.), а также управлять назначением владельца на роли. «Контейнерная иерархия» LotusScript Java NotesACL -> NotesACLEntry -> NotesACL ACL _> ACLEntry _> ACL Для создания объекта класса [NotesjACLEntry обычно используют метод createACLEntry класса [Notes]ACL. • В LotusScript для этого может также использоваться метод New. Метод New создает в объекте notesACL, представляющем ACL, новый элемент с именем пате$ (тип String) и уровнем доступа /eve/%. Dim variableName As New NotesACLEntry( notesACL, name$, level% ) или Set notes ACLEntry - New NotesACLEntry( notesACL, name$, /eve/% ) Константа, /eve/% может быть одной из следующих: • • • • • • • ACLLEVEL NOACCESS - нет доступа, ACLLEVEL_DEPOSITOR-депозитор, ACLLEVELJREADER - читатель, ACLLEVEL_AUTHOR - автор, ACLLEVEL_EDITOR - редактор, ACLLEVEL_DESIGNER - дизайнер, ACLLEVELJMANAGER - менеджер. Для доступа к существующему элементу ACL из объекта класса [NotesjACL имеются два способа: ' • если известно имя владельца элемента ACL, его элемент можно получить методом getEntry; • если имя владельца неизвестно, можно «просмотреть» все элементы методами getFirstEntry и getNextEntry. Не забывайте вызывать метод save для объекта [NotesjACL, чтобы сохранить в ACL базы изменения, произведенные вами как в объекте [NotesjACL, так и в содержащихся в нем объектах [NotesjACLEntry. Пример. Скрипт методом New создает в ACL элемент для группы Terminations, которая, как общепринято, содержит список субъектов, которым никуда нет доступа. Dim session As New NotesSession Dim db As NotesDataba.se Dim acl As NotesACL Dim entry As NotesACLEntry Set db - session.CurrentDatabase If Not. ( db.IsOpen ) Then © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java Call db.Open( "", "" } End If Set acl = db.ACL Set entry = New NotesACLEntry( acl, ACLLEVEL_NOACCESS ) Call acl.Save 471 "Terminations", 3.8.1. Свойства Свойство Parent-«родитель» LotusScript: Set notes ACL - notesACLEntry.Parent Java: ACL ad = ACLEntry.getPurentQ Объект класса [NotesJACL, содержащий данный элемент ACL. Свойство Level -«уровень доступа» -:-..'-'"'. :;... LotusScript: :•."..':• •':•'•''• level% = notesACLEntry.Lev el notesACLEntry.Level - level% Java: int level = ACLEntry.getLe\elQ void ACLEnlry.seiLe\el(int level) Уровень доступа к базе владельца этого элемента ACL. Возможные уровни доступа задаются константами: ACLLEVELJNOACCESS / ACL.LEVEL_NOACCESS - нет доступа, ACLLEVEL DEPOSITOR / ACL.LEVEL_DEPOS1TOR - депозитор, ACLLEVEL "READER / ACL.LEVEL_READER - читатель, ACLLEVEL ^AUTHOR / ACL.LEVEL_AUTHOR - автор, ACLLEVEL_ED1TOR / ACL.LEVEL_EDITOR - редактор, ACLLEVEL_DES1GNER / ACLiLEVEL_DESIGNER - дизайнер, ACLLEVELJV1ANAGER / ACL.LEVEL_MANAGER - менеджер. Пример 1. Скрипт находит в ACL- текущей базы элемент для группы LocalDomainServers и, если группа имеет к базе доступ менеджера, предоставляет ей доступ дизайнера. Dim session As New NotesSessiori Dim db As NotesDatabase Dim acl As NotesACL Dim entry As NotesACLEntry Set db = session.CurrentDatabase Set acl = db.ACL Set entry •- acl. GetEntry ( "LocalDomainServers" ) If Not ( entry Is Nothing ) Then If entry.Level = ACLLEVEL_MANAGER Then entry.Level = ACLLEVEL_DESIGNER Call acl.Save End If . End If - Пример 2. Java-агент выводит уровни доступа всех элементов ACL текущей базы. // Java-ACLEntry/LevelAgent Database db = agentContext.getCurrentDatabase{); ACL acl = db.getACL(); ACLEntry entry = acl.getFirstEntry(); String lev = null; do { switch(entry.getLevel()) © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript u Java 472 { case ACL.LEVEL_NOACCESS: lev = "no"; break ; case ACL.LEVEL_DEPOSITOR: lev = "depositor"; break; case ACL.LEVEL_READER: lev = "reader"; b r e a k; case ACL,LEVEL^AUTHOR: lev = "author"; -break; case ACL.LEVEL_EDITOR: lev = "editor"; break; case ACL.LEVEL__DESIGNER: lev = "designer"; break; case ACL.LEVELJMANAGER: lev = "manager"; break; } System.out.println(entry.getName( ) + " has "+lev+" access"); } while ( (entry = acl.getNextEntry(entry)) != null); Свойство Name - «имя владельца элемента ACL» LotusScript: . •. , name$ ~ notesACLEntry.Nsane notesACLEntry.Nstme = nameS Java: String name = ACLEntry.geiNnmeQ void ACLEntry.seiName(String name) void ACLEntry.setName(Name name) Имя владельца элемента ACL. Тип String или, в Java при установке свойства, объект класса Name, содержащий это имя. Когда вы изменяете имя, все прочие атрибуты этого элемента, например, уровень доступа и тип, сохраняются. Пример. Скрипт кнопки в форме «просит» пользователя ввести уровень доступа, а затем выбирает us ACL текущей базы список элементов, имеющих этот уровень доступа, и помещает этот список в поле Comment текущего документа. Функция GetLevelConstant служи! для преобразования введенной пользователем строки, например, "Designer", в соответствующую константу - ACLLEVEL_ DESIGNER. Sub Click(Source As Button) Dim workspace As New NotesUIWorkspace Dim uidoc As NotesUIDocument Dim session As New NotesSession Dim db As NotesDatabase Dim acl As NotesACL Dim entry As NotesACLEntry Dim LevelString As String Dim .levelConstant As Integer Set uidoc = workspace.Current Document Set db = session.CurrentDatabase Set acl = db.ACL levelString = Inputbox$( "Какой уровень доступа вас интересует?" } ' преобразуем строку в константу ACLLEVEL levelConstant = GetLevelConstant( levelString ) ' просматриваем все элементы ACL Set entry =•- acl. GetFirstEntry While Not ( entry Is Nothing ) ' если у элемента нужный уровень доступа, If ( entry.Level - levelConstant ) Then 1 добавляем имя элемента в поле People. Call uidoc.FieldAppendText( "Comment", entry.Name & "; " ) End If Set entry - acl.GetNextEntry( entry ) Wend ' Обновляем текущий документ, чтобы текстовый список ' отображался «красиво» Call uidoc.Refresh © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 473 End Sub Function GetLevelConstant ( desired.Level As String ) Dim levelConstant As Integer LevelConstant = 9999 Select Case Lease(desiredLevel) Case "manager": levelConstant = ACLLEVEL MANAGER Case "designer": levelConstant = ACLLEVEL_DESIGNER Case "editor": levelConstant -= ACLLEVEL EDITOR Case "author": levelConstant =• ACLLEVEL_ AUTHOR Case "reader": levelConstant = ACLLEVEL READER Case "no access": levelConstant = ACLLEVEL NOACCESS End Select GetLevelConstant = levelConstant. End Function - - Свойство NameObject - «объект [NotesjName для владельца элемента ACL» LotusScript: Java: Set notesName = New NotesName(notesACLEntry.Name) Name nameOhj = ^CZ.&;frv.getNameObject() В Java этот метод возвращает объект класса Name, представляющий имя владельца элемента ACL. В LotusScript аналогичного эффекта можно достичь созданием нового объекта класса NotesName, указав в качестве параметра его конструктора значение свойства Name элемента ACL. Свойства объекта [NotesjName позволяют легко извлекать из имени его различные составляющие. ® Свойства UserType, IsGroup, IsPerson, IsServer - «тип элемента ACL» LotusScript: usertype% = notesACLEntry. UserType notesACLEntry.Vsei'Type = usertype% flag ~ notesACLEn try.IsGroup notesACLEntry.lsGroup -flag flag notesACLEntry.lsPerson notesACLEntry.lsPerson —flag flag notesACLEntry.lsServer notesACLEntry.lsServer —flag Java: int user type =^CLЈw/r>'.getUserType() void A CLEntry.setlherType(int usertype) boolean flag = ACLEntry.isGroupQ void ACLEntry.$etGroup(boo!ean flag) boolean flag ~ ACLEntry.isPerson() void AC'LEntry.setPerson(boolean flag) © InterTrust Co. Тел. (095)9567928 Встроенные классы LotusScript и Java 474 boolean flag = ACLEntry.isServerQ void ACLEntry.$etServer(boolean flag) Свойство UserType позволяет определить или изменить тип элемента ACL. Тип задается константой: * ACLTYPE_Unspecified(= 0)/ACLEntry.TYPE_UNSPECIFIED - не указан, * ACLTYPEJPerson(= l)/ACLEntry.TYPE_PERSON - пользователь, * ACLTYPE_Server(= 2)/ACLEntry.TYPE SERVER - сервер, » ACLTYPE_MixedGroup(= 3)/ACLEntry.TYPE_MIXED_GROUP - «смешанная» группа, * ACI. TYPE_PersonGroup(= 4)/ACLEntry.TYPE_PERSON_GROUP - группа пользователей, » ACLTYPE_ServerGroup(= 5)/ACLEntry.TYPEJSERVER_GROUP - группа серверов. Свойства IsGroup, IsServer и IsPerson имеют значение true, если элемент ACL является группой (пользователей, серверов или «смешанной»), сервером (собственно сервером, группой серверов или «смешанной» группой) или пользователем (собственно пользователем, группой пользователей или «смешанной» группой). ', Свойство CanCreateDocuments - «может ли создавать документы» LotusScript: flog ~ notesACLEntry.CanCresteDocuments notesACLEntry.Ca.nCre&teDocnments = flag Java: boolean flag = ACLEntry.isCanCreateDocumentsQ void ACLEntry.setCanCreateDocuments(boolean flag) Для элемента с доступом автора проверяет или устанавливает признак, может ли его владелец создавать новые документы (Create documents). Если flag =: true, то может, а если false - нет. Установка свойства для элементов с иным, чем автор, доступом, не вызывает никакого эффекта. Для элементов с доступом редактора, дизайнера и менеджера свойство всегда возвращает true, а для элементов с доступом читателя, депозитора и «нет доступа» - всегда false. Для вновь созданного элемента ACL с доступом автора свойство по умолчанию устанавливается в false. ^ Свойство CanDeleteDocuments - «может ли удалять документы» LotusScript: flag~ notesACLEntrv.CanDeleteDocuments notesACLEntry.CanDeleteDocuments —flag Java: boolean flag =^CL&tfry.isCanDeIeteDocuments() void ACLEntry.setCanDeleteDovuments(boolean flag) Для элемента с доступом автора и выше проверяет или устанавливает признак, может ли его владелец удалять документы (Delete documents). Если flag == true, то может, а если false -нет. Установка свойства для элементов с меньшим, чем автор, доступом, не вызывает никакого эффекта. Для элементов с доступом читателя, депозитора и «нет доступа» свойство всегда возвращает false. Для вновь созданного элемента ACL с доступом автора и выше свойство по умолчанию устанавливается в false. Пример 1. Скрипт добавляет в ACL текущей базы имя Иван И. Иванов/Acme/RU с доступом автора и правом создавать новые документы, но без права удалять документы. Dim session As New NotesSession Dim db As NotesDatabase © InterTrust Co. Тел. (095) 9567923 _ Lotus Domino R. 5: {(^-формулы, LotusScript, встроенные классы LotusScript и Java 475 Dim Dim Set Set Set acl As NotesACL ...-•.. entry As NotesACLEntry db = session.Current Database acl = db.ACL entry = New NotesACLEntry(acl,"Иван И. Иванов/Acme/RU", ACLLEVEL AUTHOR ) entry,CanCreateDocuments = True entry.CanDeleteDocuments = False Call acl.Save Пример 2. Java-агент выполняет то же, что и скрипт в предыдущем примере. Единственное отличие - имя добавляемого элемента ACL выбирается из поля комментариев этого агента. .// Java-ACLEnt r у /CanCr Del Document sAgent Agent agent = agentContext.getCurrentAgent(); Database db = agentContext.getCurrentDatabase(); ACL acl = db.getACL();. ACLEntry entry - acl . createACLEnt. ry (agent. get.Comment () , ACL . LEVEL_ AUTHOR) ; entry.setCanCreateDocuments(true); entry.setCanDeleteDoeuments(false); acl.save{); Свойство CanCreatePersonalFolder - «может ли создавать личные виды или папки» '•'•'•'•• : •' ' . . - ' . : . - • " • ''::.:-'";.'•••:"".";•-V:"'.'.•••. '"'"'••'•-::.:'•..-.' -•'.•"''V.'..'•-:-...':;-'.-;•• LotusScript: flag — notesACLEntry.CanCresntcPersanaWolder notesACLEntry.CanCreatePersonmlFa\der —flag Java: boolean flag ~ ACLEntry.isC'dnCreatePcrsonalFolderQ void ACLEntry.setCa.nCreatePersonalFo\der(boolean flag) Признак, может или нет владелец элемента с доступом редактора, автора или читателя к базе создавать в этой базе личные папки (Create personal folders/views). Если flag ~ true, то может, а если false - нет. Для элементов ACL с доступом дизайнера и менеджера свойство всегда возвращает значение true, а для элементов с доступом депозитор и «нет доступа» - всегда false. Установка свойства для элементов с доступом, отличным от редактора, автора или читателя, не вызывает никакого эффекта. Для вновь созданного элемента ACL с доступом редактора, автора или читателя свойство по умолчанию устанавливается в false. © Свойство CanCreateSharedFolder - «может ли создавать общие виды или папки» LotusScript: flag ~ no/es^CZJi/z/ry.CanCreateSharedFolder notesACLEntry.C&nCreateSliaredFolder=flag Java: boolean flag = ^CLEnfry.isCanCreateSharedFolderQ void ACLEntry.setCanCreateSharedFolder(boo!ean flag) Признак, может или нет владелец элемента с доступом редактора к базе создавать в этой базе общие папки (Create shared folders/views). Если flag = true, то может, а если false - нет. Для элементов ACL с доступом дизайнера и менеджера свойство всегда возвращает значение true, а для элементов с доступом автора, читателя, депозитора и «нет доступа» -всегда false. Установка свойства для элементов с доступом, отличным от редактора, не вызывает никакого эффекта. Для вновь созданного элемента ACL с доступом редактора свойство по умолчанию устанавливается в false. © InterTrust Со. Тел. (095) 9567928 Встроенные классы LotusScript и Java 476 Свойство CanCreatePersonalAgent - «может ли создавать личных агентов» LotusScript: flag - woto^CZJ<r«/ry.CanCreatePersonalAgeot wotei^CLEw/ry.CanCreatePersoiialAgent = flag Java: public boolean isCanCreatePersonaiAgent () throws NotesException public void setCanCreatePersonaiAgent (boolean flag) throws NotesException Признак, может или нет владелец элемента с доступом редактора, автора или читателя к базе создавать в этой базе личных агентов (Create personal agents). Если flag = true, то может, а если false - нет. Для элементов ACL с доступом дизайнера и менеджера свойство всегда возвращает значение true, а для элементов с доступом депозитор и «нет доступа» - всегда false. Установка свойства для элементов с доступом, отличным от редактора, автора или читателя, не вызывает никакого эффекта. Для вновь созданного элемента ACL с доступом редактора, автора или читателя свойство по умолчанию устанавливается в false. © Свойство CanCreateLSOrJavaAgent - «может ли создавать агентов на LotusScript или Java». . .. .. . . ... .. ..-"•:.-:.•• ...... . . • • . . : . • . . • - • ' LotusScript: flag ~ «0/e&4CЈ.E«fry.CanCreateLSOrJavaAgent woto/4CLЈ»/rv.CanCreateLSOrJavaAgent -flag Java: boolean flag = ^CZj&tfry.isCanCreateLSOrJavaAgentQ void ,^CiЈ^ry.setCanCreateLSOrJavaAgent(Z>oo/<?a« flag) Признак, может или нет владелец элемента с доступом читателя, автора, редактора, или дизайнера к базе создавать в этой базе агенты на LotusScript или Java (Create LotusScript/Java agents). Если flag = true, то может, а если false - нет. Для элементов ACL с доступом менеджера свойство всегда возвращает значение true, a для элементов с доступом депозитор и «нет доступа.» - всегда false. Установка свойства для элементов с доступом, отличным от дизайнера, редактора, автора или читателя, не вызывает никакого эффекта. Для вновь созданного элемента ACL с доступом дизайнера, редактора, автора или читателя свойство по умолчанию устанавливается в false. Свойство IsPublicReader - «может ли читать общедоступные документы» LotusScript: flag = notesACLEntry.IsPablicReader notesACLEntry.lsPvib}ieReader=flag Java: boolean flag ~- ACLEntry.isPublicRe&derQ void ACLEtitry.setPublicR.eader(boolean flag) Признак, может или нет владелец элемента, имеющий к базе доступ депозитор или «нет доступа», читать в этой базе общедоступные документы (Read public documents). Если flag = true, то может, а если false - нет. Для элементов ACL с доступом выше депозитора свойство всегда возвращает значение true. Установка свойства для элементов с доступом выше депозитора не вызывает никакого эффекта. Для вновь созданного элемента ACL с доступом депозитор и «нет доступа» свойство по умолчанию устанавливается в false. © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 477 Свойство IsPublic Writer - «может ли создавать общедоступные документы» LotusScript: flag = notesACLEntry.IsPublicWnter notesACLEntry,ls,Public\Vriter = flag Java: boolean flag ~ ACLEntry.isPublicWriterQ voidACLEntry.setPu.blicWriter(boelean flag) Признак, может или нет владелец элемента, имеющий к базе доступ автора, читателя, депозитора или «нет доступа», создавать в этой базе общедоступные документы (Write public documents). Если flag - true, то может, а если false - нет. Для элементов ACL с доступом выше автора свойство всегда возвращает значение true. Установка свойства для элементов с доступом выше автора не вызывает никакого эффекта. Для вновь созданного элемента ACL с доступом автора и ниже свойство по умолчанию устанавливается в false. © Свойство IsAdminServer- «является ли сервером администрирования базы» : . . . .... . .... . . .."." LotusScript: flag = notesACLEntry.lsAdmmServer notesACLEntry.IsAdmmServcr = flag Java: boolean flag = ACLEntry.isAdminServerQ void ACLEntry.setAdminServer(boolean flag) Признак, является ли данный элемент ACL сервером администрирования этой базы. Если flag = true, то является, а если false - нет. © Свойство IsAdminReaderAuthor - «разрешается ли серверу администрирования базы изменять в ней поля типа Readers и Authors» LotusScript: flag ~ notesACLEntry.lsAdminReauerAuthor notcsACLEntry.lsAdminReaderAuthor -flag Java: boolean flag = ACLEntry.isAdminReaderA.uihor() void ACLEntry.setAdminRe-MlerAutbor(boolean flag) Признак, разрешается ли данному элементу ACL, представляющему сервер администрирования базы, изменять в базе поля типа Readers и Authors при выполнении запросов по изменению имен или удалению пользователей или серверов. Если flag = true, то разрешается, а если false - нет. Пример. Java-агент запускается с рабочей станции администратора и проверяет наличие на заданном сервере баз, для которых не был назначен сервер администрирования. Если это возможно, этот сервер назначается сервером администрирования такой базы. //Java-ACLEntry/SetAdminServer String server = "Domino500/InterTrustCorp/SU"; DbDirectory Dir = session.getDbDirectory(server); Database db = Dir . get.FirstDatabase (DbDirectory. REPLICA_CANDIDATE) ; if ( db != null ) ( do ' { try { db.open(); } catch(Exception e) // нет доступа { System, out .println ( "Not opened " i- db . getFilePath { ) ) ; © InterTrust Co. Тел. (095)9567928 478 Встроенные классы LotusScript и Java db. recycle() ; continue; ..,.,. , .• } ACL acl « db.getACL{); ' if {acl. isUnif ormAccess { ) =-- true) // такие трогать опасно { System, out. println ( "Unif ormAccess for " <- db.getFilePath()); db.recycle(); continue; } "''•''" ':';" ": int. accLevel = db . getCurreritAccess'Levei ( ) ; if (accLevel != ACL.LEVEL MANAGER) : \ Syst em. out .pr int ln ( " Not MAN AGE R f or " + db.g etF ile Fat h () ); db.recycle (); continue; } boolean got It = true; AC LEn t г у en t. г у - а с 1. g e t Fir s t En t г у () ; do { if(entry .isAdminServer () == true) f g o t l t = f al s e ; // с е р ве р а д м ин и с тр и ро в а ни я у ж е н а зн а ч ен break; } } while ( (entry = acl.getNextEntry(entry )) != null); if (gotlt === true) // нет сервера администрирования { System, out. .println ("* + * Database " -f db. getFilePath ( ) + " ..."); AC LE n t r y s e n t r y = ac l . ge t E nt ry ( s e r ve r ) ; if (sentry == null) sentry = acl.createACLEntry(server,ACL.LEVEL J4ANAGER) ; it (sentry i= null) . { . . . sent ry. set Can Del ete D ocum ent s(t rue ) ; sentry.setUserType(ACLEntry.TYPE_SERVER) ; sent ry . set Adm inS erv e r(tr ue) ; sent ry. set Adm inR ead e rAut hor (fa lse ) ; acl.save(); System.out.println("... AdminServer") ; , } ' } db.recycle(); } while ( (db = Dir. get NextDatabase ( ) } ! r= null); } Свойство Roles - «роли, на которые назначен владелец элемента ACL» LotusScript: stringArray — notesACLEntry.Roles Java: java.util. Vector roles - ACLEntry.geiRolesQ Возвращает роли (в LotusScript тип Array of strings, в Java - объект класса java.util. Vector с элементами класса String), на которые назначен владелец элемента ACL. Каждое имя роли возвращается в квадратных скобках, например: "[Project Leader]". Пример 1. Скрипт выводит все роли, на которые назначен Иван И. Иванов/Acme/RU. Например, скрипт мог бы выдать "[Project Leader]" и "[Writer]". Dim session As New NotesSession Dim db As NotesDatabase Dim acl As NotesACL © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 479 Dim entry As NotesACLEntry Set db = session.CurrentDatabase Set acl = db.ACL Set entry = acl .GetEntry( "Иван И, Иваноа/Acme/RU" ) Forall r In entry,Roles Messagebox( r } End Forall Пример 2. Подобно предыдущему примеру, Java-агент выводит все роли, на которые назначен субъект, имя которого агент получает из «своего» поля комментариев. import Java -ut.il .Vector; // Java-ACLEntry/RolesAgent Agent agent = agentContext.getCurrentAgent(); Database db = agentContext.getCurrentDatabase (); ACL acl = db.getACL(); ACLEntry entry -- acl. getEntry (agent. getComment ()); i f ( en t r у ! -- nu .11} I Vector roles = entry.getRoles(); if (roles.size() == 0) System.out.println(entry .getName() + " has no roles"); else { System.out.println(entry .getName() + " has the following role(s ):"); for (int i = 0; i < roles.size(); i++) System, out. println (" " +• roles . elementAt (i) ) ; } } 3.8.2. Методы Метод isRoleEnabled - «назначен ли на роль» LotusScript: Java: flag = no1esACLEntry.isRo}eEnableu(rolename$ ) boolean flag — notesACLEntry.isRoleEnabled(String rolename} Для имени роли rolename (тип String) возвращает true, если владелец элемента ACL назначен на эту роль, или false, если нет. Имя роли следует задавать «в квадратных скобках». Если указанное имя роли отсутствует в ACL, в LotusScript последует ошибка, а в Java будет возбуждено исключение "Role name not found". Пример. Скрипт создает в интерфейсе пользователя новый документ. Однако для тех, кто назначен на роль "[Supervisor]", этот документ создается по форме approval, а для прочих - по форме request. Dim workspace As New NotesOIWorkspace Dim session As New NotesSession Dim uidoc As NotesUIDocument Dim acl As NotesACL Dim entry As NotesACLEntry Set. db = session.Current.Databa.se Set acl = db.ACL Set entry = acl.GetEntry( session,CommonUserName ) If entry.IsRoleEnabled( "[Supervisor]" ) Then Set uidoc = workspace.ComposeDocument( "", "approval" ) E1 s e Set uidoc = workspace.ComposeDocument( "", "request" ) End I f © InterTrust Co. Ten. (095)9567928 Встроенные классы LotusScript и Java 480 Метод EnableRole - «назначить на роль» LotusScript: Call notesACLEntry,^nst\3\eVio\e(rolename$) Java: voidACLEnlry.enableRole(String rolename) Назначает владельца элемента ACL на роль, имя которой задано параметром rolename. Имя роли следует задавать «без квадратных скобок». Если указанное имя роли отсутствует в ACL, в LotusScript последует ошибка, а в Java будет возбуждено исключение "Role name not found". Если роль существует, но владелец элемента уже назначен на эту роль, нечего не изменится. Выполненные назначения вступят в силу только после сохранения ACL методом save. Пример I. Скрипт кнопки вызывает подпрограмму enablePeople, которая в ACL текущей базы назначает на роль [Роль 1] всех субъектов, перечисленных в списке names. Sub Click(Source As Button) Dim session. As New NotesSession Dim db As NotesDatabase Dim acl As NotesACL Dim entry As NotesACLEntry Set db = session.CurrentDatabase Set acl - db.ACL Dim names List As Variant names("1") = "Nikolay N. lontsev/InterTrustCorp/SU" names("2") = "LocalDomainServers" names("3") = "Иван И, Иванов/Acme/RU" names("4") = "John П. Иванов/Acme/RU" Dim role As String role = "Роль 1" Call enablePeople(acl, role, names) End Sub Sub enablePeople ( acl As NotesACL, role; As String, names As Variant ) Dim person As NotesACLEntry Forall ri In names Set person ^ acl. Get.Entry ( n ) If person Is Nothing Then Set person = New NotesACLEntry( acl, n, ACLLEVEL_READER ) End If Call person.EnableRole( role ) Print n; " enabled the role ["; role; " ] " End Forall Call acl.Save End Sub ' Пример 2. Java-агент назначает все элементы ACL текущей базы на роль, имя которой выбирается из моля комментариев агента. Предварительная проверка, что элемент уже назначен на роль, не является необходимой, но приведена, чтобы продемонстрировать применение метода isRoleEnabled. /' / Ja va - AC LEn try /Enable Role Agent Agent agent - agentContext.getCurrentAgent(); Database db = agentContext.getCurrentDatabase ( ) ; ACL acl = db.getACL(); ACLEntry entry = acl.getFirstEntry{) ; do { if (entry.isRoleEnabled(agent.getComment())) { System.out.println(agent.getComment() + " is already enabled for " + entry. getName ()); } © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 481 else { entry.enableRole(agent.getComment( ) ) ; System.out.println(agent.getCoiranent(} + " enabled for " + entry.getName( ) ) ; } } while { (entry = acl.getNextEntry(entry)) ' = null); acl.save (); Метод disableRole - «ликвидировать назначение на роль» LotusScript: Call notesACLEntryMs»bleRolK(roIenameS) Java: voidACLEnlry.<\isable:Ro\e(String rolename) Ликвидирует назначение владельца элемента ACL на роль, имя которой задано параметром rolename. Имя роли следует задавать «без квадратных скобок». Если указанное имя роли отсутствует в ACL, в LotusScript последует ошибка, а в Java будет возбуждено исключение "Role name not found". Если роль существует, но владелец элемента не назначен на эту роль, нечего не изменится. Выполненные назначения вступят в силу только после сохранения ACL методом save. Метод remove - «удалить элемент из ACL» LotusScript: Call notesACLEntry.i'eniQ've Jav я: vo id A CLEntry. rem ove() ',.. ::.. :... ..: ' : . . • ; . . . . . • .; :;. ,: Удаляет элемент из ACL. Изменения вступят в силу после сохранения ACL. Учтите, что субъект, элемент которого вы удалили из ACL, возможно, сможет получить доступ к базе как член группы или -Default-. Пример I. Скрипт находит сервер Development/InterTrustCorp/SU в ACL текущей базы и удаляет его из ACL. Dim session As New NotesSession Dim db As NotesDatabase Dim acl As NotesACL Dim entry As NotesACLEntry Set db = session.CurrentDatabase Set acl = db.ACL Set entry = acl.GetEntry( "Development/InterTrustCorp/SU" ) If Not (entry Is Nothing) Then Call entry.Remove Call acl.Save , . ' , End If Пример 2. Java-агент находит элемент ACL, имя которого указано в поле комментариев агента, и удаляет этот элемент из ACL. /7 Java-ACLEntry/RemoveAgent Agent agent = agentContext.getCurrentAgent(); Database db = agentContext.getCurrentDatabase( ) ; ACL acl = db.getACL(}; ACLEntry entry = acl.getEntry(agent.getComment( ) ) ; if (entry != null) { entry.remove(); acl.save(); } ' © InterTrust Co. Тел, (095)9567928 Встроенные классы LotusScript и Java 482 3.9. «Иерархическая навигационная схема» - класс [Notes]Outline Новый класс в Domino версии 5 - [Notes]Outline - предназначен для работы с элементом дизайна Outline - «иерархической навигационной схемой». Навигационная схема в свою очередь состоит из набора иерархически («древовидно») упорядоченных элементов, выбор которых пользователем влечет выполнение некоторого действия или перехода по ссылке. Каждый элемент схемы характеризуется своим положением и уровнем в схеме и может иметь «родителя» и «потомков». Уровень элемента в схеме исчисляется с нуля. Для работы с элементом схемы в LotusScript или Java используется объект класса [Notes]OutlineEntry. Рис. 3.21 Внешний вид Outline как элемента дизайна (в окне Domino Designer) «Контейнерная иерархия» LotusScript Java NotesDatabase _» NotesOutline Database —» Outline -> —> NotesOutlineEntry OutlineEntry Свойства объекта [NotesjOutline «немногочисленны» - название, алиас и комментарий. Методы объекта [Notes]Outline позволяют осуществлять навигацию по элементам, входяешм в схему, создавать новые элементы, добавлять их в необходимое место в схеме, перемещать существующие элементы в схеме и удалять их. Для того, чтобы все модификации, выполненные «программно» в объекте [Notes(Outline, были сохранены в базе, необходимо вызвать метод save. Рис. 3.22 Окно свойств Outline как элемента дизайна Для создания новой иерархической навигационной схемы используется метод createOutline класса [NotesJDatabase - он создает в базе новый элемент дизайна и возвращает ссылку на представляющий его объект класса [NotesJOutline. Для доступа к существующей навигационной схеме можно использовать метод getOutline класса [NotesJDatabase, однако и © InterTrust Co. Тел. (095) 9567928 Lotus. Domino R. 5: (<£м$<чшулы,. LotusScript, встроенные классы LotusScript и Java 483 метод createOutline в случае, когда схема уже существует в базе, будет возвращать тот же самый объект. 3.9.1. Свойства © Свойство Name - «название схемы» LotusScript: пате$ — notesOutline.'Name по1езОиШпе.1$яте = пате$ Java: String name - OM//w<?.getNameQ void Ou(line.seiName(String name) Имя иерархической навигационной схемы как элемента дизайна. ® Свойство Alias - «алиас схемы» LotusScript: Java: пате$ = notesOutline.A\ia.$ String пате - Oz////ne.getAHasQ notesOutline.Alias ~ пате$ void Outline.setAli&s(String пате) Алиас (альтернативное название) иерархической навигационной схемы как элемент; дизайна. © Свойство Comment - «комментарий к схеме» LotusScript: пате$ = notesOutline.Comment : S notesOuiIine.Comment = пате$ Java: String пате — 0M///>?e.getComment() void Outline.setComment(String пате) Комментарий к иерархической навигационной схеме как элементу дизайна. 3.9.2. Методы для навигации по элементам схемы © Метод getFirst - «получить первый элемент из схемы» LotusScript: SetnotesOutlineEntry — notesOutline.getҐirst() Java: OutlineEntry entry - Outline.geiFirstQ -, Возвращает первый элемент из объекта [Notes]Outline или Nothing/null, если его нет. @ Метод getNext - «получить следующий за указанны м элемент» .....-.... .-.:..ч.••:'.:" LotusScript: Set nextNotesOutlineEntry — notesOutline,^,eiNe\t( NotesOutlineEntry) Java: OutlineEntry nextEntry = Outline.geiNeTit(OutlineEntry entry) Возвращает элемент из объекта [NotesJOutline, следующий за элементом, заданнь параметром метода, или Nothing/null, если его нет. .. . ©Метод getLast- «получить последний элемент из схемы» LotusScript: Set notesOullineEntry = notesOulline.gKtLast( ) Java: OutlineEntry entry = Outline.geiLast() . . .... ..:.-:.. Возвращает последний элемент из объекта [NotesjOutline или Nothing/null, если его нет. Встроенные классы LotusScript и Java 484 @ Метод getPrev - «получить предшествующий указанному элемент» LotusScript: Set prevNotesOuiUneEntry = notesOutline.getPrev( NotesOutlineEntry ) Java: OutlineEntry prevEntty — Outline.geiPrev^OutlineEntry entry) Возвращает элемент из объекта [Notes]Outline, предшествующий элементу, заданному параметром метода, или Nothing/null, если его нет. © Метод getNextSibiing - «получить следующий за указанным элемент того же уровня» LotusScript: Set nextSibNotes Outline Entry ~ notesOutline.geiNe\tSib\\ng( NotesOutlineEntry) Java: OutlineEntry nextSibEntry = Oiitlit-ie.gct'Ne^tSiblhi^OutlineEntry entry) Возвращает элемент из объекта [NotesJOutline, следующий за элементом, заданным параметром метода, и имеющий тот же уровень. Например, на Рис. 3.21 для элемента с именем «Презентация» таким окажется элемент с именем «New Entry4». Ехли такого элемента не существует, возвращается Nothing/null. © Метод getPrevSibling - «получить предшествующий указанному элемент .. тогожеуровня» •' ' . • •' . " •. ' -. ' • ::;'••:...::.'--.-•..'•.. ,^-•••..•-'..-..•.•::-'. • - . . ": ' :. :' ; LotusScript: Set prevSibNotesOutlineEntry ~ «o/esOw////2e.getPrevSibImg( NotesOutlineEntry ) Java: OutlineEntry prevSibEntry ~ Outline.getPrevSib\ing(OutlmeEntry entry) Возвращает элемент из объекта [NotesJOutline, предшествующий элементу, заданному параметром метода, и имеющий тот же уровень. Если такого элемента не существует, возвращается Nothing/null. © Метод getParent - «получить элемент, являющийся родителем указанного» LotusScript: Set parentNotesOutlineEntry = , notesOutline,getParent( NotesOutlineEntry ) Java: OutlineEntry parentEntry = Outline.getParent(OutlineEntry entry) Возвращает элемент из объекта [NotesJOutline, являющийся «родителем» для элемента, заданного параметром метода. Например, на Рис. 3.21 для элемента с именем «Пример 2» таким окажется элемент с именем «Презентация». Если такого элемента не существует, возвращается Nothing/null. 3.9.3, Прочие методы © Метод createEntry - «создать для схемы новый элемент» LotusScript: Java: : • .... . . - :: Set notesOutlineEntry - notesOutline.createEntry( entryNameS) OutlineEntry entry = Outline.createEntry (String entryName) Создает в схеме новый элемент с именем, заданным параметром entryName (тип String), и возвращает представляющий его объект класса [Notes]OutlineEntry. Этот элемент «еще не © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (а)-формулы, LotusScript, встроенные классы LotusScript и Java 485 добавлен в определенное место в схеме», и для осуществления этого необходимо воспользоваться методом addEntry. © Метод addEntry - «добавить новый элемент в схему» LotusScript: Call note$Outline.mdd'Entry( newEntry [ , re/Entry [, after ] [, asChild ]] ) Java: void Outline.add'Entry(OutlineEntry newEntry, OutlineEntry re/Entry) void Outline.addE>ntry(OullineEnlry newEntry, OutlineEntry re/Entry, boolean after) void Outline.•AUAE.atry(OutlineEntry newEntry, OutlineEntry refEntry, boolean after, boolean asChild) Добавляет в объект [Notes]Outline новый элемент newEntry (объект класса [NotesjOutlineEntry). Элемент добавляется после или перед элементом, заданным параметром refEnlry (объект класса [NotesjOutlineEntry). Добавление происходит «после» , если флаг after опущен или равен true, и «перед», если флаг after равен false. Чтобы добавить первый элемент в «пустую схему» или «за последним существующим элементом», нужно опустить параметр refEntry или задать его равным null. Если флаг asChild опущен или равен true, добавляемый элемент становится потомком элемента refEntry. Если флаг asChild равен false, добавляемый элемент будет иметь тот же уровень, что и элемент refEnlry. Учтите, что добавление нового элемента «как потомка перед указанным элементом» не допускается. © Метод moveEntry - «переместить существующий элемент в схеме» LotusScript: Call notesOutline,moveEntry( movedEntry [, refEntry [, after ][, asChild ]]) Java: void Outline.moveE,ntry(OutlineEntry movedEntry, OutlineEntry refEntry) void Ontline.moveEntry(OutlineEntry movedEntry, OutlineEntry re/Entry, boolean after) void Outline.mQve~Entry(OutlineEntry movedEntry, OutlineEntry refEntry, boolean after, boolean asChild) Перемещает в объекте [NotesJOutline существующий элемент movedEntry (объект класса [NotesjOutlineEntry). Элемент помещается после или перед элементом, заданным параметром refEntry (объект класса [NotesjOutlineEntry). Перемещение выполняется «в позицию после элемента», если флаг after опущен или равен true, и «перед», если флаг after равен false. Если флаг asChild опущен или равен true, перемещаемый элемент становится потомком элемента refEntry, Если же флаг asChild равен false, перемещаемый элемент будет иметь тот же уровень, что и элемент refEnlry, Учтите, что «за перемещаемым элементом в новое местоположение последуют и все его потомки». © Метод removeEntry - «удалить существующий элемент из схемы» LotusScript: Call notesOutline.removeEntry( NotesOutlineEntry) Java: void Outlme.rEmoveEntry(OutlineEntry entry) Удаляет из объекта [NotesJOutline существующий элемент - объект класса [NotesjOutlineEntry. Учтите, что вместе с удаляемым элементом удаляется и все его потомки. © Метод save - «сохранить схему» . • . . . . LotusScript: • •: . • •••...,. , . : - •••:•••.•••..:•-:':::;:.;.. Call notesOutline.save © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 486 Java: void Outline.s&\eQ Для того, чтобы все модификации, выполненные в объекте объекта [NotesJOutline, были сохранены в элементе дизайна Outline в базе, необходимо вызвать метод save. Пример 1. Скрипт получает иерархическую навигационную схему с именем Outline! и сначала выводит информацию о составляющих ее элементах, их количестве и количестве уровней. Затем скрипт добавляет в схему вслед за ее последним элементом новый элемент «как потомка». Dim s As New NotesSession Dim db As notesDataba.se Set db = s.CurrentDatabase Dim о As notesOutline Set о = db.GetOutline( "Outlinel" ) Dim oe As notesOut.lineEn.try Dim oe.Last As notesOutlineEntry Л Set oe — o.GetFirstQ n = 0 maxLev -~ 0 While Not ( oe Is Nothing ) n = n + 1 If maxLev < oe.Level Then maxLev = oe.Level Messagebox "OutlineEntry #" & Cstr(n) S " Level" & Cstr(oe.Level) & " : " & oe.Label Set oeLast = oe Set oe = о.GetNext( oe ) Wend Messagebox "Элементов " & Cstr(n) & " Уровней " & Cstr(maxLev+1) Dim oeNew As notesOutlineEntry Set oeNew = о.CreateEntry{"New Entry" & Cstr(rH-l)) Call oeNew.SetURL("http:/'/dominoSOO"} Call o.AddEntry (oeNew, oeLast} Call о.Save Messagebox "Добавлена новая OutlineEntry" Пример 2. Java-агент выполняет те же действия, что и скрипт в предыдущем примере. //Java-Outline/Exl Database db =-- agentContext. getCurrentDatabase (} ; Outline о = db.getOutline{"Outlinel"); OutlineEntry oe = о.getFirst(); OutlineEntry oeLast = null; int n = 0; int. maxLev = 0; while ( oe != null ) { n - n + 1; if (maxLev < oe.getLevel()} maxLev = oe.getLevel(); System .out. println ( "OutlineEntry it" + n + " Level" + oe . getLevel () + " : " + oe.getLabel()); oeLast = oe; oe = o.getNext( oe }; } System.out.println("Элементов " + n + " Уровней " + (maxLev+1)); OutlineEntry oeNew = о.CreateEntry("New Entry" + (n+1)); oeNew.set URL("http://dominoSOO") ; о.addEntry (oeNew, oeLast); о.save(); о.recycle(); System.out.println("Добавлена новая OutlineEntry") ; © InterTrust Co. Тел. (095) 9567928 Lotus Domino R, 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 487 3.10, «Элемент навигационной схемы» - класс [NotesjOutlineEntry Класс [NotesjOutlineEntry - новый класс в Domino версии 5, позволяющий работать с элементом, входящим в состав иерархической навигационной схемы (Outline). Каждый элемент схемы имеет имя и алиас, может иметь пиктограмму, быть «видимым» или «скрытым», характеризуется типом и классом, и, наконец, имеет или ссылку на ресурс, который «открывается» при выборе элемента пользователем в текущем окне или заданном фрейме-«мишени», или действие, заданное @-функцией и выполняемое при выборе элемента пользователем. Свойства класса [NotesjOutlineEntry во многом соответствуют возможностям, доступным в окне свойств элемента навигационной схемы в Domino Designer. Puc, 3.23 Окна свойств элемента навигационной схемы в Domino Designer Методы класса [NotesjOutlineEntry позволяют определять для элемента ссылку на ресурс на базу данных Notes, вид или документ в базе, на элемент дизайна в базе (форму, страницу, набор фреймов, вид, папку, навигатор), на ресурс в Internet - или выполняемое при выборе элемента действие, которое определяется @-формулой. «Контейнерная иерархия» LotusScript Java NotesOutline —> Outline —> NotesOutlineEntry —> NotesDatabase NotesView NotesDocument OutlineEntry — > Database View Document Для создания объекта класса [NotesjOutlineEntry, представляющего новый элемент схемы, используют метод createEntry класса [NotesJOutline, а для получения объекта для существующего элемента схемы - различные методы класса [NotesJOutline. 3.10.1. Свойства © Свойство Label - «метка элемента» LotusScript: text$ - notesOutlineEntry.l&bel notesOutlineEntry.luabel — texlS < InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 488 Java: String text = OutlineEntry.getLabelQ void OutlineEntry.seiL&be\(String text) Метка (название) элемента иерархической навигационной схемы. © Свойство Alias - «алиас элемента» LotusScript: textS = notesOtitlineEntry.Alias notesOutlineEntry.Alias = text$ Java: String text = OutlineEntry.getAlmsQ void OutlineEntr)>.setAlias(String text) Алиас (альтернативное название) элемента иерархической навигационной схемы. © Свойство IsHidden - «скрытый ли» LotusScript: flag = notesOutlineEntry.lsHidden notesOutlmeEntry.lsHidtlen -flag Java: boolean flag - OutlineEntry,isHidden() void OutlineEntry.seiHidden(booiean flag) Значение true, если элемент схемы «скрытый», или false, если он «виден» в интерфейсе пользователя. © Свойство IsPrivate - «общий или частный» • : . . ':v• : : LotusScript: flag = notesOutlineEntry.IsPrivate Java: boolean flag = OutlineEntry,iPtiv&te() Возвращает true, если элемент схемы «частный», или false, если он «общий». © Свойство ImagesText - «файл с изображением пиктограммы для элемента» LotusScript: imageS = notesOutlineEntry.Im.agesText note$OutlineEntry.Imag,es'Te\t:~ image $ Java: String image = OM///neЈ'«/ry.getImagesText() voidOutlineEntry.seilm»gesTe\t(String image) Строка с именем файла, содержащего изображение пиктограммы для этого элемента схемы. Сам же этот файл должен содержаться в графических ресурсах базы. © Свойство Level - «уровень в иерархической навигационной схеме» LotusScript: level& = notesOutlineEntry.~Level Java: int level = OutlineEntry.geiLevelQ Целое число (тип Long/int), дающее уровень элемента в иерархической навигационной схеме. Для элемента на самом старшем уровне Level == 0. © InterTrust Со. Тел. (095) 9567928 Lotus Domino R, 5: @гформулы, LotusScript, встроенные классы LotusScript и Java 489 © Свойство HasChildren - «имеет ли потомков» LotusScript: flag - notesOutlineEntry.HasCbildren Java: boolean flag = OutlineEntry.hasCbMrenQ Возвращает true, если элемент схемы имеет потомков, или false, если не имеет. © Свойство Туре - «тин элемента» LotusScript: . , .-....• •....•.-.... ;."\'.•'..••'.-.. type& — notesOtttlineEnlry.Type notesOutlineEntry^ype - type& Java: int type = OutlineEntry.getTypeQ Константа типа Long/int характеризующая тип элемента схемы: » OUTLINE_TYPE_NOTELrNK/OutiineEntry.OUTLlNE_TYPE_NOTELTNK - ссылка на базу Notes (Database Link), вид (View Link) или документ (Document Link); * OUTLINE_TYPE_NAMEDELEMENT/OutlineEntry.OUTLlME_TYPE_NAMEDELEMENTссылка на элемент дизайна из базы Notes (форму, страницу, набор фреймов, вид, папку, навигатор) по его имени; OUTLINE^TYPEJURL/OutlineEntry.OUTLINEJTYPEJJRL - ссылка на ресурс в Internet по URL; OUTLlNE_TYPE_ACTION/OutlineEntry.OUTLlNE_TYPE_ACTION действие, описываемое @-формулой; , ;••• OUTLINE_OTHER_VlEWS_TYPE/OutlineEntry.OUTLINE_OTHER_VIEWS_TYPE ссылка на виды других типов; OUTLINE_OTHER_FOLDERS_TYPE/OutlineEntry.OUTLINE_OTHER_FOLDERS_TYPE ссылка на папки других типов; OUTLINE_OTHER_UNKNOWN_TYPE/OutlineEntry.OUTL[NE_OTHER_UNKNOWN_TY РЕ - другой тип. . ., . * « * * * © Свойство Entry Class - «класс элемента» . • LotusScript: Java: . . . , . ; •;;; - •::': •• ..•.... , ;....:.,. .;:-:•:.; • :•; ... entryClass% — notesOutlineEntry.'EntryCfass int entryClass -•=- OutlineEntry.getEntryClassQ Константа типа Integer/int, характеризующая класс элемента схемы: * * * * * * OUTLINE_CLASS_DATABASE/OutlineEntry.OUTLINE_CLASS_DATABASE - ссылка на базу данных Notes (Database Link); OUTLINE_CLASS_DOCUMENT/OutlineEntr>'.OUTLINE_CL,ASS_DOCUMENT - ссылка на документ в базе данных Notes (Document Link); OUTlJNE_CLASS_VIEW/OutlineEntry.OUTLINE_CLASS_VIEW - ссылка на вид в базе данных Notes; OUTLINE CLASS FOLDER/OutlineEntry.OUTLlNE CLASS_FOLDER - ссылка на папку в базе данных Notes; OUTLI>JE_CLASS_FORM/OutlineEntry.OUTLINE_CLASS_FORM - ссылка на форму в базе данных Notes; OUTLlNE_CLASS_PAGE/OutlineEntry.OUTLINE_CLASS__PAGE - ссылка на страницу в базе данных Notes (Database Link); © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 490 • OUTLINE_CLASS_FRAMESET/OutlineEntry.OUTLINE_CLASS_FRAMESET - ссылка на набор фреймов в базе данных Notes; ® OUTLINE_CLASS_NAVIGATOR/OutlineEntry.OUTLINE_CLASS_NAVIGATOR - ссылка на навигатор в базе данных Notes; * OUTLlNE_CLASS_UNKNOWN/OutlineEntry.OUTLINE_CLASS_UNK"NO\VN класс. - другой © Свойство IsInThisDb - «ссылается ли на ресурс в данной базе» LotusScript: flag- notesOutlineEntry.IslnThisDb Java: boolean flag = OutlmeEntry.islnthisDbQ Возвращается true, если элемент схемы «ссылается» на какой-то ресурс из данной базы (из которой был получен объект [NotesjOutline, «содержащий» объект [NotesjOutlineEntry), или false, если нет. © Свойство Database - «база, на которую ссылается элемент схемы» LotusScript: Set notesDatabase ~ notesOutlmeEntry.Database Java: Database db = OutlineEntry.getDatsibaseQ Если элемент схемы имеет run OUTL1NE_TYPE_NOTELINK или OUTL1NE_TYPE NAMEDELEMENT и класс OUTLINE CLASS_DATABASE, OUTLINE_CLASS_DOCUMENT или OUTLINE_CLASS_VIEW, то "возвращается объект класса [Notes]Database, представляющий базу, на которую «ссылается» элемент схемы. В противном случае возвращается Nothing/null. © Свойство View - «вид, на который ссылается элемент схемы» •-.'••.•• • LotusScript: Java: • ... Set notesView = notesOutlineEntry.View View view = OutlineEntry.get\iewQ Если элемент схемы имеет тип OUTLfNE_TYPE_NOTELINK и класс OUTLJNE_CLASS_DOCUMENT или OUTLINE CLASS VIEW, то возвращается объект класса [Notes]View, представляющий вид, на который «ссылается» элемент схемы. В противном случае возвращается Nothing/null. © Свойство Document - «документ, на который ссылается элемент схемы» LotusScript: Java: Set notesDocument — notesOutlineEntryJDocument Document doc — OutlineEntry.geiDocumentQ Если элемент схемы имеет тип OUTLINE_ TYPE_NOTELINK и класс OUTLTNE_CLASS_ DOCUMENT, то возвращается объект класса [NotesJDocument, представляющий документ, на который «ссылается» элемент схемы. В противном случае возвращается Nothing/null. © Свойство NamedElement-«название элемента дизайна, на который ссылается элемент схемы» :. .. •" . . ' ; . : . LotusScript: name$ = notesOutlineEntry.NaLmedElement Java: Siring пате ~ Oz///weЈ'7?/ry.getNamedEIement() © InterTrust Co. Тел, (095) 9567928 : Lotus Domino R. 5: @-фармулы, LotusScript, встроенные классы LotusScript и Java 491 Если элемент схемы имеет тип OUTLINE TYPE_NAMEDELEMENT, то возвращается название или алиас элемента дизайна, на который «ссылается» элемент схемы. В противном случае возвращается «пустая» строка. © Свойство URL - «URL ресурса, на который ссылается элемент схемы» LotusScript: url$ - notesOittIineEntry.lJRL Java: String url - OutlineEntry.getURLQ Если элемент схемы имеет тип OUTLINE_TYPE_URL, то возвращается URL ресурса в Internet, на который «ссылается» элемент схемы. В противном случае возвращается «пустая» строка. ® Свойство Formula - «@-формула, выполняемая при выборе элемента схемы» ' . • .- : .'.•• ••" ••."••> ;•'-"..'-: . ;• • •-: ;•;•;-.-": у V. ': •• • : ' •' ' ;. ••-' •- ; '':\УLotusScript: formulaS = notesOullineEntry.Formula Java: String formula = OutlineEntry.geiFormu\»() Если элемент схемы имеет тип OUTLINE TYPE ACTION, то возвращается строка, содержащая текст @-формулы, которая выполняется при выборе пользователем элемента схемы. В противном случае возвращается «пустая» строка. © Свойство FrameText - «имя фрейма-мишени» LotusScript: frame$ ~ notesOutlineEntry.FramsText notesOtitlineEntry.'FrumeText ~frame$ Java: String frame = OutlineEntry.getFrameTextQ void OutlineEnlry.seiFrameText(_Stri'ng frame) Строка с именем фрейма (из текущего набора фреймов), в который должен помещаться ресурс (страница, документ, вид...), на который «ссылается» элемент схемы. Пример. Java-агент формирует отчет о свойствах всех элементов схемы с именем Outline2. Если эта схема была сформирована агентом .lava-Outline/ЕхЗ (см. пример в конце подраздела 3.10.2), то этот отчет будет выглядеть следующим образом, *** Outline2 ***Alias: ExSComment: Примеры создания элементов cxeMbiNoteLink to Database Type: Note link Entry class: Database Level: 0 Does not refer to an element in this db Entry is publicNarnedElement of VIEW class Type: Named element Entry class: View Level: ! Does not refer to an element in this db Entry is publicURL www.inttrust.ruType: URL Entry class: Unknown Level: 1 Does not refer to an element in this db Entry is publicACTION ToolsRunMacro Type: Action Entry class: Unknown Level: 1 Does not refer to an element in this db Entry is public // Java-Outline/Ex2 Database db = agentCoritext. getCurrentDatabase (); Outline о = db.getOutline("Outline2"); System, out .println ("*** " + o.get.Name() + " ***"),System, out. printlri ( "Alias : " + o. get.Alias () ) ; System.out.println("Comment: " + о.getComment()}; OutlineEntry e = о.getFirst(); while (e != null.) • { • System.out.println(e.getLabel()); . © InterTrust Co. Тел. (095) 9567928 492 Встроенные классы LotusScript u Java if (e.getAlias ().length () > 0) System, out.. println ( "\tAlias : " + e.getAlias()); String type = null; switch (e.getType()) \ cas e Out l i neE nt ry .OU TLI NE OT HE R F OL DE RS TYP E: typ e = " Ot her f ol der s"; b rea k; case OutlineEntry.OUTLINE OTHER_VIEWS TYPE: type — "Other views"; break; case OutlineEntry.OUTLINE_OTHER UNKNOWN TYPE: type = "Other unknown"; break/ case OutlineEntry.OUTLINE_TYPE_ACTION: type = "Action"; break; case OutlineEntry .OUTLINE_TYPE NAMEDELEMENT : typ e = " Na med e le men t"; b rea k; case Out].ineEntry.OUTLINE_TYPE_NOTELINK: type -•• "Note link"; break; case OutlineEntry.OUTLINE TYPEJJRL: type = "URL"; break; } System, out . print In ( "\tType : " + type); String entryClass = null; switch (e.getEntryClass ()) { case OutlineEntry. OUTLINE__CLASS DATABASE: ent ry Cla ss = "D at aba se" ; bre ak ; case OutlineEntry.OUTLINE CLASS_DOCUMENT: ent ry Cla ss - "D oc ume nt" ; bre ak ; case OutlineEntry.OUTLINE_CLAS S_FORM: ent ry Cla ss = "F or m"; br ea k; case OutlineEntry.OUTLINE_CLASS FOLDER: ent ry Cla ss = "F ol der "; br eak ; case OutlineEntry.OUTLINE_CLASS FRAMESET: ent ry Cla ss - "F ra me set "; br ea k; case OutlineEntry.OUTLINE CLASSENAVIGATOR : ent ry Cla ss = " Na vi ga tor "; b rea k; case OutlineEntry.OUTLINE CLASS_PAGE: entryClass = "Page"; break; case OutlineEntry, OUTLINE_CLASS__UNKNOWN: ent ry Cla ss = "U nk now n"; b rea k; case OutlineEntry.OUTLINE_CLASS_VIEW: entryClass -= "View"; break; } System.out.println ("\tEntry class: " + entryCl ass}; Sys te m .o ut .pr in tl n (" \tL ev el : " + e. ge tLe vel () ); if (e.isInThisDB()) Sys te m.o ut .pr in tl n (" \tR ef ers to an el em e nt i n t h i s d b " ) ; e 1 se System.out .println (" \tDoes not refer to a n element in this db" ); if (e.isPrivate<)) System.out .println (" \tEntry is pr ivat e " ) ; e 1 se System.out.print In("\tEntry is public") ; if fe.getFrameText() .length() > 0) System.out.println {"VtFrame text: " 4 e, g etFrameText ()); if (e.getlnagesText ().length () > 0) System, out: . print In ( "\tlmages text: " + e . get ImagesText () ) ; e = о.getNext (e) ; } © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 493 3.10.2. Методы @ Метод setNoteLink - «определить ссылку на базу, вид или документ» LotusScript: flag = notesOullineEntry.seiNoteLink( notesDatabase, nolesView, notes Document) Java: boolean /Jag = OutlineEntry.set'NotelAnk(Database db) boolean flag = Ot(tlineEntn\setNote'Lmk(Fiew view) boolean flag - OutlineEntry.seiNoteLink(Document doc) Устанавливает для элемента схемы в качестве ссылки на ресурс ссылку на базу Notes, вид или документ в базе, заданный в качестве параметра метода. В LotusScript методу должен передаваться только один параметр соответствующего класса. Одновременно устанавливает для элемента тип OUTLINE TYPE_NOTELINK и класс OUTLINE_CLASS DATABASE, OUTLINE_CLASS_DOCUMENT или" OUTLINE_CLASS_VIEW в зависимости от класса переданного параметра. Возвращает true, если операция завершилась успешно. 0 Метод setNamedEIement - «определить ссылку на элемент дизайна» LotusScript: flag - notesOutlineEntry.seiNamed'Element( notesDatabase, elernentNameS, entryClass% ) Java: boolean flag -= OutlineEntry.seiNamedElemeni(Database db, Siring elementName, int entry-Class) Устанавливает для элемента схемы в качестве ссылки на .ресурс ссылку на элемент дизайна из базы Notes (форму, страницу, набор фреймов, вид, папку, навигатор), имя которого заданно параметром elementName, а класс - параметром entryClass (константа типа Long/int, определения констант приведены в описании свойства EntryClass). Одновременно устанавливает для элемента тип OUTL1NE_TYPE NAMEDELEMENT и класс, заданный параметром entryClass. Возвращает true, если операция завершилась успешно. 0 Метод setURL - «определить ссылку на ресурс в Internet»- . . . : • . : :., •.- ... ,.. LotusScript: flag = notesOutlineEritry.setURL( urlS ) Java: boolean flag - OutlmeEr(try.setURL(Slring url) Устанавливает для элемента схемы в качестве ссылки ссылку на ресурс в Internet с заданным URL (тип String). Одновременно устанавливает для элемента тип OUTLINE_TYPE URL. Возвращает true, если операция завершилась успешно. © Метод setAction - «определить формулу действия» LotusScript: flag = notesOutlineEntry.setA.ction( formufaS) Java: boolean flag - OittlineEntry.setAction(String formula) Устанавливает для элемента схемы формулу действия, заданную в строке formula. Одновременно устанавливает для элемента тип OUTLINE TYPE_ACTION. Возвращает true, если операция завершилась успешно. Пример. Java-агент создает новую или добавляет в существующую схему с именем Outline2 четыре элемента разных типов. Созданная схема в Domino Designer выглядит следующим образом. © InterTrust Co. Тел. (095) 9567928 494 Встроенные классы LotusScript и Java // Java-Outline/Ex3 Datcibase db - agentContext. getCurrentDatabase () ; Outline о = db.createOutline("Outline2") ; o.setAlias("Ex3") ; о.setCominent("Примеры создания элементов схемы"); System.out.print In("Creating entry TYPE_NOTELINK. . .") ; OutlineEntry e = о.createEntry("NoteLink to Database"!; e.setHidden(false); e.setlmagesText("abook.gif"); e.setNoteLink(db); о.addEntry(e, null, true); System.out.println{"Creating entry TYPE_NAMEDELEMENT..."); e - o. createEntry("MamedElement of VIEW class"); e.setHidden(false); e . setlmagesText("vwtrash.gif"); e.setNamedElement(cib, "($A11)",OutlineEntry.OUTLINE_CLASS_VIEW) о.addEntry(e, о.getLast() , true) ; System.out.println("Creating entry TYPE _URL. . . ") ; e = о.createEntry("URL www.inttrust.ru"); e.setHidden(false); e.setlmagesText{"graphic. gif") ; e.setURL("http://www.inttrust.ru"); о.addEntry(e, o.getLast(), true, false); System.out.println("Creating entry TYPE ACTION..."); e = o. createEntry ( "ACTION ToolsRunMac.ro"); e.setHidden(false); e.setlmagesText("vwinbox.gif"); e.setAction("@Coiomand([ToolsRunMacro];\"Java-Outline\\\\Ex3\")" о.addEntry(e, о.getLast (), true, false); ) InterTrust Co, Тел. (095) 9567928 Lotus Domino R. 5: ((^формулы, LotusScript, встроенные классы LotusScript и Java 495 3.11. «Агент» - класс [NotesJAgent Объект этого класса представляет агента. Свойства класса [NotesjAgent позволяют «узнать» название агента, комментарии к нему и имя его владельца (лицо, модифицировавшее агента последним), определить, общий это агент или личный, выполняется он в среде Notes или предназначен для запуска из Web-броузера, разрешено или запрещено его выполнение, на каком сервере он должен выполняться, каков способ его запуска, какое множество документов им обрабатывается, какой «поисковый» запрос использует для отбора коллекции обрабатываемых документов, выполнялся ли агент хотя бы раз и когда он в последний раз выполнялся. Методы класса [Notes]Agent позволяют сохранить агента в базе (после изменения имени сервера, на котором должен выполняться агент, или «разрешения на выполнение»), инициировать запуск агента, а также удалить агента из базы. «Контейнерная иерархия» LotusScript Java NotesSession _> NotesDatabase AgentContext Database NotesAgent -» Agent —> _> NotesDatabase Database DateTime Получить объект класса [NotesjAgent можно двумя способами. Если необходим объект, представляющий агента, который выполняется в настоящее время, используют свойство CurrentAgent класса NotesSession/AgentContext. Если необходим доступ ко всем агентам базы, используют свойство Agents класса [Notes]Database. 3.11.1. Свойства Свойство Parent - «родитель» LotusScript: Set notesDatabase = notesAgent.Varent Java: Database db = Agent.geiParentO Возвращает объект класса [NotesJDatabase, представляющий базу, в которой определен агент. Пример. Скрипт агента получает доступ к базе, в которой он выполняется. • Dim session As New NotesSession Dim db As NotesDatabase Dim agent As NotesAgent Set agent = session.CurrentAgent Set d b = age nt. Pa re n t Свойство Name - «название агента» LotusScript: agentName$ ~ notcsAgent.Name Java: String agentName - Agent.getNameQ Название агента (тип String). Учтите, что в одной базе может существовать несколько агентов с одинаковым названием. Пример. Java-агент выводит имена всех агентов, имеющихся в текущей базе. import j ava.util.Vector; // Agent/Name Database db — agentContext.getCurrentDatabase() ; © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 496 Vector agents = db.getAgents(); System.out.println("Agents in database:"); for (int. i=0; i < agents. size (); i + +) { Agent agent = (Agent)agents.elementAt(i); System.out.println(" " + agent.getName()); ) Свойство Comment - «комментарий» LotusScript: comments = notesAgent.CQmment Java: String comment = Agent.getCommentQ Возвращает комментарии (тип String), «записанные» по поводу агента его разработчиком. Пример. Скрипт по текущей базе формирует отчет обо всех общих агентах, выполнение которых разрешено. Для каждого такого агента дается его название и комментарии. Отчет помещается в поле Body нового документа, который затем отсылается всем менеджерам текущей базы, Dim session As New NotesSession Dim db As NctesDatabase Dim doc As NotesDocument ,< Dim rtitem As NotesRichTextltem Set db = session.CurrentDatabase Set. doc = New NotesDocument ( db ) Set rtitem = New NotesRichTextltem( doc, "Body" ) Forall a Tn db.Agents If ( a.IsPublic And a.IsEnabled ) Then Call rtitem.AppendText( a.Name.) Call rtitem.AddTab( 2 ) Call rtitem.AppendText( a.Comment ) Call rtitem.AddNewLine( 1 ) End If End Forall doc.Subject = "Сводка по общим агентам в базе " & db.Title Call doc.Send( False, db.Managers ) Свойство Owner - «полное имя владельца агента» LotusScript: ownerNameS ~ notesAgent.Owner Java: Siring ownerName ~ Agent.getO~wner() Л Полное имя владельца агента (тип String). Владельцем агента считается тот, кто последним модифицировал данного агента. Это справедливо, ибо если пользователь запустил агента, ожидая при этом, что агент должен переносить документы с пометкой «Для служебного пользования» в другую базу с ограниченным доступом, а агент вместо этого переслал документы по адресу в фирме-конкуренте и удалил их в текущей базе, то ответственность за произошедшее несет разработчик, модифицировавший агента последним. Пример. Предположим, что агента создал Yukiko Kitarmura/Tokyo/Production, а последним модифицировал Mariko Ikebuchi/Tokyo/Production. Строка owner будет содержать "Mariko Ikebuchi/Tokyo/Production". ' created by Yukiko Kitamura 11/28/98 ' modified by Mariko Ikebuchi 12/17/98 Dim session As New NotesSession Dim agent As NotesAgent Dim owner As String © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: @-формулы, LotusScript, встроенные классы LotusScript и Java 497 Set agent = session.CurrentAgent owner -- agent. Owner Свойство CommonOwner - «общее имя владельца агента» LotusScript: commonOwner$ — notes Agent.CommonQytner Java: String commonOwner — Agent.getCommonQwnerQ Общее имя (составляющая CN= из полного имени) владельца агента (тип String). Пример. Предположим, что Java-агента создал Yukiko Kitarmura/Tokyo/Production, а последним модифицировал Mariko Ikebuchi/Tokyo/Production. Последняя строка будет содержать "Common owner: Mariko Ikebuchi". // Agent/CommonOwner // created by Yukiko Kitamura 11/28/98 // modified by Mariko Ikebuchi 12/17/98 Agent agent = agentContext.getCurrentAgent(); System, out. println ( "Current agent is \"" -i agent. getName () + "\""); System, out .println ( "Common owner: " 4- agent. getCommonOwner ()); Свойство IsPublic - «общий ли агент» -. '."•'•- ' :••. ..,: ..."••. ...-••••••• ... • LotusScript: flag = notesAgent.isPublic Java: boolean flag-• AgentAsVublic() Возвращает true, если агент общий (public), или false, если он «личный» (person). Общий агент доступен всем пользователям базы и физически хранится в базе. Личный агент обычно доступен только его владельцу, а физически может хранится как в базе, так и в файле DESKTOP.DSK на станции владельца. Свойство IsEnabled - «разрешено ли выполнение агента» LotusScript: flag = notesAgent.isEnabled notesAgent.hEnabled -flag Java: boolean flag = AgentAsEnabledQ void Agent.seiE n a bled (boolean flag) • Возвращает true, если выполнение агента разрешено, или false, если запрещено. Свойство имеет смысл только для агентов, выполняемых по расписанию или событию создания/модификации документа или получения почты (после получения). Для агентов других типов свойство всегда возвращает true. После изменения значения свойства необходимо «применить к агенту» метод save. «Признаком» агентов, выполняемых по расписанию или событию создания/модификации документа или получения почты (после получения), является наличие «прямоугольника» —* или ^ в первом столбце списка агентов в Domino Designer (Ошибка! Источник ссылки не найден.). Если «в прямоугольнике имеется галочка», выполнение такого агента разрешено, иначе запрещено. Кроме того, для агентов, выполняемых по расписанию или событию создания/модификации документа, в окне Построителя агентов имеется кнопка Schedule. Нажатие этой кнопки влечет появление окна Schedule, в котором можно выбрать компьютер для выполнения такого агента и разрешить или запретить его выполнение. Однако для агентов, выполняемых по событию получения почты (после получения), компьютером для выполнения всегда является почтовый сервер владельца агента. Можно только разрешить или запретить выполнение такого агента, например, «щелчком мыши по соответствующему прямоугольнику» в списке агентов. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 498 Рис. 3.24 Список агентов в Domino Designer . Пример. Java-агент разрешает выполнение агента с именем Agent To Enable в текущей базе. import ] ava.util.Vector; // Agent/Enabled Database db = agentContext.getCurrentDatabase() ; Vector agents = db.getAgents(); int count - agents.size(); int i; for (i = 0; i < count; i++) . . . . Agent agent — (Agent)agents.elementAt(i}; String name = agent.getName(); if (name == null) name = "No name"; if (name . compareTo ( "Agent To Enable") r== 0) { if ( agent. isEnabled{) == false ) { agent.setEnabled(true); agent.save(); } System.out.println("agent found and enabled"}; break; } } if (i == count) System.out.println("agent not found"); © Свойство IsNotesAgent - «может ли быть выполнен в среде Notes».. - ; .-.-•.- . LotusScript: flag - notesAgent.isNoteskgent Java: boolean flag = Agent.isNotesAgentQ Возвращает true, если данный агент может быть выполнен в среде Notes, т.е. в окне свойств агента на закладке Disign не выбрана опция Hide design element from: Notes 4.6 or later clients, или false, если эта опция выбрана. © Свойство IsWebAgent - «может ли быть выполнен в среде Web» LotusScript: flag = notesAgent.isWeb&gcnt © InterTrust Co. Тел. (095) 9567928 Lotus Domino R. 5: (а)-формулы, LotusScript, встроенные классы LotusScript и Java Java: 499 boolean flag = ,4g<?«/.isWebAgent() Возвращает true, если запуск данного агента на сервере Domino может быть инициирован из броузера, т.е. в окне свойств агента на закладке Design не выбрана опция Hide design element from: Web Browser, или false, если эта опция выбрана. Пример. Java-агент для каждого агента текущей базы выводит значения свойств isNotesAgent и isWebAgent. import java.uti1.Vector; // Agent/isNotesWebAgent Database db = agentContext.getCurrentDatabase(); Vector agents =;; db.getAgents(); for (int i = 0; i < agents.size(); i + +) { Agent agent. - (Agent) agents . elementAt (i) ; System.out.print In(agent.getName() ); if (agent.isNotesAgent()} System.out.println(" is a Notes agent"); else System.out.println(" is not a Notes agent"); if (agent.isWebAgent()) System.out.print In(" is a Web agent"); else System.out.println(" is not a Web agent"); } Свойство ServerName - «компьютер, на котором долясен выполняться агент» LotusScript: serverS = notesAgent,ServerName notesAgent.ServerName - serverS Java: String server — j4gen/.getServerName() void Agent.setServerName(String server) Значение свойства (тип String) определяет компьютер, на котором должен выполняться агент. Возможны следующие случаи. * * * Если агент выполняется по расписанию или событию создания/модификации документа в базе на сервере, свойство возвращает имя сервера, на котором должен запускаться агент. Поскольку обычно такой агент обычно должен работать только в одной реплике базы, должно быть выбрано имя сервера для выполнения агента (см. окно «кнопки» Schedule). Поэтому свойство может вернуть как имя сервера, на котором находится ваша база, так и имя сервера, с которым ваша база реплицируется - в зависимости от того, в какой из реплик действительно должен работать агент. Однако допустимы и агенты, которые должны выполняться в каждой реплике базы. Для таких агентов свойство возвращает строку "*". Соответственно для изменения значения свойства необходимо задать полное имя сервера или строку "*", а после изменения значения свойства «применить к агенту» метод save. Если агент выполняется по событию получения почты (после получения) в базе на сервере, свойство обычно возвращает имя сервера, являющегося почтовым сервером владельца агента. Для изменения значения свойства необходимо задать полное имя нового сервера, а после изменения значения свойства «применить к агенту» метод save. Однако, если в файле NOTES.INI нового сервера отсутствует переменная AMgr DisableMailLookup = 1, то сервер не станет выполнять этого агента, когда имя сервера для выполнения агента не совпадает с именем почтового сервера владельца этого агента. Если агент выполняется по расписанию в базе на станции пользователя, свойство возвращает полное имя пользователя. Для изменения значения свойства необходимо задать полное имя пользователя, а после изменения значения свойства «применить к агенту» метод save. © InterTrust Co. Тел. (095) 9567928 Встроенные классы LotusScript и Java 500 • Для агентов других типов свойство как в LotusScript, так и в Java, возвращает «пустую строку» (""). Изменение значения свойства в этом случае не имеет смысла. © Свойство Trigger - «способ запуска агента» LotusScript: trigger% - notesAgent.Trigger Java: int trigger = Agent.getTriggerQ Возвращает целое число, позволяющее определить способ запуска («триггер») агента: • • TRIGGER_MANUAL7Agent.TRIGGERJMANUAL - «вручную» из пользователя, TRIGGER_SCHEDULED/Agent.TRIGGER_ SCHEDULED - по расписанию, интерфейса. • TRIGGER_DOC_PASTED/Agent.TRIGGER_DOC_PASTED - по событию копирования документа в базу из буфера обмена, • TRIGGER_DOC_UPDATE/Agent.TRlGGER DOC UPDATE - по событию создания или модификации документа в базе, • TRlGGER_BEFORE_MAIL_DELIVERY/Agent.TRlGGER_BEFORE_MAIL_DELIVERY- по событию получения почты (перед получением), ® TRIGGER_AFTER_MAIL_DELIVERY/Agent.TRlGGER_AFTER_MAlL_DELlVERY - по событию получения почты (после получения) • TRIGGER_NONE/Agent.TRlGGER_NONE - агент не выполняется. © Свойство Target - «множество документов, обрабатываемых агентом» LotusScript: target% - nolesAgenl.Target Java: int target = Agent.getTurgetQ Возвращает целое число, позволяющее определить множество документов, обрабатываемых агентом (выбирается разработчиком в поле Which document(s) should it act on? окна Построителя агентов): » TARGET__ALL_DOCS/Agent.TARGET_ALL_DOCS - все документы в базе (All documents in database), в TARGET_NEW_OR_MODIFIED_DOCS/Agent.TARGET_NEW_OR_MODIFIED_DOCS новые или модифицированные документы (All new or modified documents since last run), • TARGET UNREAD _DOCSJN_VlEW/Agent.TARGET_UNREAD _DOCS _IN_VIEW «непрочитанные» пользователем документы из вида (All unread documents in view), • TARGET^ ALL DOCS IN VIEW/Agent.TARGET ALL DOCS__JN_VIEW - все документы из вида (All documents in view), • TARGET SELECTED DOCS/Agent.TARGET SELECTED DOCS выбранные пользователем документы (Selected documents), • TARGET_NEW_DOCS/Agent.TARGET_NEW_DOCS - новые документы, • TARGET NONE/Agent.TARGET_NO:NE - отсутствует. Пример. Java-агент для каждого агента из текущей базы выводит значения свойств Target и Trigger. Заметим, что в Domino версии 5.0а для агентов Run once свойство Target возвращает значение 8, что не соответствует определению константы Agent.TARGETJNONE = 0. import Java.util.*; // Agent/TargetTrigger Database db = agentContext.getCurrentDatabase(}; Enumeration agents = db.getAgents(),elements(}; © InterTrust Co. Тел. (095) 9567928