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

  • Автор темы lionk
  • Дата начала
L

lionk

задумался механизмами контроля изменения значения полей.

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

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

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

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

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

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

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


Первоисточник решения
 
M

morpheus

dataTypeName - строка, попробуйте вписать имя поля, должно сработать.

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

lionk

HashPassword не канает она всеголиш мешает значение строки

serEJa Shabalin

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

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

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

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

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

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

Код:
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

народ плиз киньте се кнопочку с кодом у вас таже ошибка?
 
S

serEJa Shabalin

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

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

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

Вычисление хэш-кода
Код:
	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))

Проверка хэш-кода
Код:
	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
 
L

lionk

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

Yakov

lionk,
функция notesDocument.GetItemValueCustomDataBytes(itemName$, dataTypeName$) вычитывает данные, записанные при помощи notesDocument.ReplaceItemValueCustomDataBytes(itemName$, dataTypeName$, byteArray).
Lotus Domino Designer Help сказал(а):
ReplaceItemValueCustomDataBytes method
dataTypeName$
String. A name for the data type. When getting custom data, use this name for verification.

GetItemValueCustomDataBytes method
dataTypeName$
String. The name of the data type. This name must match the data type name specified when the item was written.
Чтобы понять, как это работает, запишите что-нибудь процедурой notesDocument.ReplaceItemValueCustomDataBytes() и посмотрите значение поля.
Поле itemName$ будет содержать:
1) длину строки dataTypeName$,
2) саму строку dataTypeName$ в бинарном виде (кодировка utf8?),
3) байтовый массив byteArray.
К примеру, после вызова notesDocument.ReplaceItemValueCustomDataBytes("field1", "123", byteArray) поле "field1" будет содержать следующие байты:
0x03 0x31 0x32 0x33 byteArray
 
L

lionk

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

Omh

Я бы заюзал глобальный List as String и свойство Item.text.
Хотя с хешем идея, безусловно, интереная...
 
L

lionk

от блин адское C API :rolleyes:

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

Akupaka

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

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

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

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

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

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

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

lionk

но не факт, что она существует отдельно от клиента, т.е. не то, что она есть - скорее факт, но можно ли ее вызвать из скрипта не факт...

:D факт или не факт вот он, вопрос. Должна ли великая душа сносить удары рока......
(посмеялсо, без обид)

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

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

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

Akupaka

а смысл его хешировать-то? :( мне кажется, что операция сравнения пройдет проще...
можно и без классов, но классом удобнее - не надо шариться с кучей переменных, достаточно одной - объекта...
 
L

lionk

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

но всё это мечты, такшо тему можно закрывать
 
30.05.2006
1 345
12
BIT
0
про LastModified подумал в первую очередь,
там дата сохранеия документа, тоесть не важно изменились ли данные внутри поля а дата поменяется и станет равной NotesDocument.LastModified
Ни фига. Это свойство имеется у каждого item-а, а не только у документа.

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

Обучение наступательной кибербезопасности в игровой форме. Начать игру!