Хеш значений нескольких полей

Тема в разделе "Lotus - Программирование", создана пользователем lionk, 17 сен 2008.

  1. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    задумался механизмами контроля изменения значения полей.

    тоесть нужно выполнять какието действия если поле било изменино и документ сохранён, для этого нужно знать былоли изменено поле <_<

    раньше на onOpen в переменные захонялись значения полей а в postSave сравнивал с текущими значениями, если не равно значит поле поменялось.

    но такой механизм меня не устраивает, появилось чуть времени решил оптимизировать:
    в моей задаче не важно знать какое именно поле менялось, важно знать что изменение произошло,
    как мне кажется удобно будет пользоватся таким алгоритмом:
    на onOpen считать хеш - суму данных определённого количества полей,
    хранить эту суму в глобальной переменной ну или в поле,
    а на postSave снова считать хеш и сравниать, так получу сигнал о том что значения поменялись

    такой механизм становится становится легконастраиваемым, и применимым к многим задачам где нужен контроль за изменениями данных

    я обратил внимание на функцию bytes = curdoc.GetItemValueCustomDataBytes( itemname , dataTypeName )
    она вроде должна вернуть масив байт значения поля (к такому масиву пременить простой алгоритм хешированя плёвое дело)
    но проблема в том что данная функция не пашет загвоздка в втором параметре(тип данных)
    пробывал так
    Set item = curdoc.GetFirstItem(x)
    bytes = curdoc.GetItemValueCustomDataBytes( item.name ,item.type )
    не работает :(

    ктото знает как пользоватся данной функцией?
    может есть идеи по реализации хеширования значения полей другими методами?
     
  2. serEJa Shabalin

    serEJa Shabalin Гость

    Решение основывается на сравнении OnDisk значения и значения на экране
    На QuerySave повесить следующий код

    Sub Querysave(Source As Notesuidocument, Continue As Variant)
    Dim db As NotesDatabase
    Dim doc As NotesDocument
    Dim noteid As String

    Set doc = Source.Document
    Set db = doc.ParentDatabase
    noteid = doc.NoteID
    Delete doc
    Set doc = db.GetDocumentByID(noteid)
    'Теперь сравнивайте по полям документы Source.Document и doc
    End Sub


    Первоисточник решения
    http://194.87.13.59/site/itforum.nsf/49341...33;OpenDocument
     
  3. morpheus

    morpheus скриптописец

    Регистрация:
    7 авг 2006
    Сообщения:
    3.927
    Симпатии:
    0
    dataTypeName - строка, попробуйте вписать имя поля, должно сработать.

    ну можно попробовать ф-цию HashPassword (это если я правильно понял зачем оно надо)
     
  4. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    HashPassword не канает она всеголиш мешает значение строки

    serEJa Shabalin

    Ваш метот прикольный но он позволяет избавится токо от глобальных переменных с старыми значениями и пременим только до Querysave.

    хочецца более независимого инструмента <_<

    битовая хеш сума позволяет отвязатся от контроля содержимого поля(текст, число, список) ведь это нужно учитывать сравнивая равно ли старое значение новому.

    а получив битовый масив неважно чего это масив строчки или вложения

    вот код
    при выполненн получаю ошибку
    "Supplied Data type name Does not match stored CustomData type"

    поле обычное ТЕХТ, значение "111"

    Код (Text):
    x="Untitled"
    If curdoc.HasItem(x) Then
    Set item = curdoc.GetFirstItem(x)
    bytes = curdoc.GetItemValueCustomDataBytes( item.Name ,item.Name) ' здесь ошибка
    Forall b In bytes
    customData = customData + Chr(b)
    End Forall
    Messagebox customData,, "Custom data"

    Else
    Messagebox "No item in document",, "No TenBytesItem"
    End If
    народ плиз киньте се кнопочку с кодом у вас таже ошибка?
     
  5. serEJa Shabalin

    serEJa Shabalin Гость

    Я немного поторопился с ответом <_<

    Кстати я отвязывался от контроля содержимого через свойство NotesItem.Text, может вам это пригодиться.
    Дополнительно у любого NotesItem есть свойство LastModified, которое указывает когда изменилось поле синоним SeqNum. Может вам к нему привязаться. У меня получилось следующее:

    Вычисление хэш-кода
    Код (Text):
        Dim session As New NotesSession
    Dim ws As New NotesUIWorkspace
    Dim doc As NotesDocument
    Dim i As Integer
    Dim text As String

    Set doc = ws.CurrentDocument.Document
    text = ""
    For i = 1 To 4
    text = text & doc.GetFirstItem("Data_" & Cstr(i)).Text
    Next
    Call doc.ReplaceItemValue("Hash", session.HashPassword(text))
    Проверка хэш-кода
    Код (Text):
        Dim session As New NotesSession
    Dim ws As New NotesUIWorkspace
    Dim doc As NotesDocument
    Dim i As Integer
    Dim text As String

    Set doc = ws.CurrentDocument.Document
    text = ""
    For i = 1 To 4
    text = text & doc.GetFirstItem("Data_" & Cstr(i)).Text
    Next
    If session.VerifyPassword(text, doc.GetItemValue("Hash")(0)) Then
    Messagebox("Изменений не произошло")
    Else
    Messagebox("Произошли изменения")
    End If
     
  6. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    про LastModified подумал в первую очередь,
    там дата сохранеия документа, тоесть не важно изменились ли данные внутри поля а дата поменяется и станет равной NotesDocument.LastModified
     
  7. Yakov

    Yakov Гость

    lionk,
    функция notesDocument.GetItemValueCustomDataBytes(itemName$, dataTypeName$) вычитывает данные, записанные при помощи notesDocument.ReplaceItemValueCustomDataBytes(itemName$, dataTypeName$, byteArray).
    Чтобы понять, как это работает, запишите что-нибудь процедурой notesDocument.ReplaceItemValueCustomDataBytes() и посмотрите значение поля.
    Поле itemName$ будет содержать:
    1) длину строки dataTypeName$,
    2) саму строку dataTypeName$ в бинарном виде (кодировка utf8?),
    3) байтовый массив byteArray.
    К примеру, после вызова notesDocument.ReplaceItemValueCustomDataBytes("field1", "123", byteArray) поле "field1" будет содержать следующие байты:
    0x03 0x31 0x32 0x33 byteArray
     
  8. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    от блин, а других способов получить содержимое поля как масив битовой информации нельзя?
     
  9. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Я бы заюзал глобальный List as String и свойство Item.text.
    Хотя с хешем идея, безусловно, интереная...
     
  10. Yakov

    Yakov Гость

    Можно, используя C API.
     
  11. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    от блин адское C API :rolleyes:

    это предлагаете писать длл?
    есть какието реальные предложения по C API, где можно поискать апишные функции работы с полями?
     
  12. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    как вариант, можно инкапсулировать все дело в класс, в нем будет три метода:
    1) конструктор
    принимает параметром массив, содержащий все те имена полей, которые нужно сравнивать
    смотрит указанный массив имен полей, и создает структуру (массив, список), содержащий данные из указанных полей документа в виде Variant
    т.е. фактически, каждый элемент массива - Variant-массив = значению в поле

    2) метод сравнения всех нужных полей
    сравнивает указанные поля с текущими значениями в полях документа
    возвращает значение в зависимости от результата сравнения, т.е. все равны, то правда, иначе ложь
    фактически использует в цикле третий метод, как только получает ложь от 3-го метода, то возвращает результат, прервав цикл

    3) метод сравнивающий два варианта
    сравнивает два указанных варинта, сравнивает их тип, данные
    возвращает значение в зависимости от результата сравнения, т.е. равны, то правда, иначе ложь

    на onOpen создать экземпляр класса
    в postSave вызов 2го метода

    минусы:
    - неудобство вызова конструктора - необходимо предварительно создать параметр-массив, но если нотес 6 и выше, то можно использовать split();
    - объем занимаемой объектом памяти;

    зы: думаю, что особого смысла от использования АПИ таким образом, т.е. обработкой каждого поля в отдельности, не будет...
    если искать АПИ-функцию, то уже ту, которая используется клиентом для определения изменился ли док и предлагать ли его сохранить, но не факт, что она существует отдельно от клиента, т.е. не то, что она есть - скорее факт, но можно ли ее вызвать из скрипта не факт...

    надеюсь, понятно изъяснился :rolleyes:
     
  13. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    :D факт или не факт вот он, вопрос. Должна ли великая душа сносить удары рока......
    (посмеялсо, без обид)

    можно всё и без класов организовать простыми функциями, иметь в конфигураторе поле где хранить миена полей которые нужно контролировать, на открытии в циклле брать их значения в список, потом сравнивать с списком, но это опять те же яйца токо в профиль.

    я так понимаю что идея хеша нереализуема так как невозможно получить содержимое поля на низком уровне(масив бит), хешировать текст - это изврат

    чтож значит не судьба :(
     
  14. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    а смысл его хешировать-то? :( мне кажется, что операция сравнения пройдет проще...
    можно и без классов, но классом удобнее - не надо шариться с кучей переменных, достаточно одной - объекта...
     
  15. lionk

    lionk Well-Known Member

    Регистрация:
    5 апр 2007
    Сообщения:
    308
    Симпатии:
    3
    смысл хеша всех конролируемых полей - одна переменная сигнализирующая о изменении какогото поля
    время выполнения хеширования и сравнения недумаю что будет различатся (если операция получения биотвого содержимого поля не дольше операции просто получения содержимого поля)
    ну и самое интересное, не важно содержимое поля (например волжение, или ин-лайн обект), ведь все вышеперечисленые методы позволяют контролировать токо текстовые поля.

    но всё это мечты, такшо тему можно закрывать
     
  16. Constantin A Chervonenko

    Constantin A Chervonenko Well-Known Member

    Регистрация:
    30 май 2006
    Сообщения:
    1.291
    Симпатии:
    0
    Ни фига. Это свойство имеется у каждого item-а, а не только у документа.

    Тонкость: правильное значение у этого св-ва - в back-ground, если док-т открыт в ui - там лажа. Но в ui изменение поля легко ловится сравнением с onDisk-value
     
Загрузка...

Поделиться этой страницей