Функция обхода документов-ответов, ответов на ответы и т.д.

  • Автор темы FixeR
  • Дата начала
F

FixeR

#1
Вобщем нужна фунция, чтобы в одну коллекцию собирались все ответы, ответы их ответов и так далее.
Наверняка у кого-нибудь есть такая, поделитесь пожалста :)
Можно с рекурсией, можно без, неважно.

Сам писал такую два года назад как-то с двумя циклами, без рекурсии, а щас третий день не могу вспомнить...
 

hosm

* so what *
18.05.2009
2 442
6
#2
в КБ есть обработка ответов: http://codeby.net/forum/threads/17552.html
там сбор юнидов, в принципе, на коллекцию переписать не сложно, имхо.
Единственное - код я не проверяла.


Добавлено: там рекурсия

Добавлено: тут вот по вьюхе брали:
Код:
Sub getAllChildren(view As NotesView, doc As NotesDocument, coll As NotesDocumentCollection)
' рекурсия
Dim childs As NotesDocumentCollection, child As NotesDocument

Set childs = view.GetAllDocumentsByKey(doc.UniversalID, True)
If childs.Count = 0 Then Exit Sub

Set child = childs.GetFirstDocument
While Not child Is Nothing
Call coll.AddDocument( child )
Call getAllChildren(view, child, coll)

Set child = childs.GetNextDocument( child )
Wend	
End Sub
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 586
272
#3
можно через нафигатор
 

VladSh

начинающий
Lotus team
11.12.2009
1 262
6
#4
Мой старый код:

Код:
%REM
Sub TreeRDownC
Description: Возвращает дерево ответов переданного документа 
%END REM
Sub TreeRDownC(ND_Source As NotesDocument, NDC_Rez As NotesDocumentCollection)
If ND_Source Is Nothing Then Exit Sub
Dim NDС As NotesDocumentCollection
Dim ND As NotesDocument
Set NDC = ND_Source.Responses
If NDC.Count = 0 Then Exit Sub

On Error 4469 Resume Next

Set ND = NDC.GetFirstDocument
Do
If IsDocAccessed(ND, false) Then	'Обнаружил баг с параметром TIA
Call NDC_Rez.AddDocument(ND)
Call TreeRDownC(ND, NDC_Rez)
End If

Set ND = NDC.GetNextDocument(ND)
If ND Is Nothing Then Exit Do
Loop
End Sub
Код:
%REM
Sub IsDocAccessed
Description: Определяет, доступен ли документ
%END REM
Function IsDocAccessed(ND As NotesDocument, SetNothing As Boolean) As Boolean
If Not ND Is Nothing Then
If ND.IsValid And Not IsEmpty(ND.Items) And Not ND.IsDeleted Then	'Добавил проверку на Items, т.к. действительно бывают траблы; спасибо сообществу!
IsDocAccessed = True
Exit Function
End If
End If
If SetNothing Then Set ND = Nothing
End Function
Если надо получить полное дерево от верхнего документа, то вызываем сначала:
Код:
%REM
Sub GetTopDoc
Description: Возвращает самый верхний документ коллекции
Если у документа нет ответа, то ND_Parent будет равно Nothing.
%END REM
Sub GetTopDoc(ND_Source As NotesDocument, ND_Parent As NotesDocument)
Dim NDB As NotesDatabase
Dim ND As NotesDocument
Set NDB = ND_Source.ParentDatabase

On Error 4091 Goto Err4091
Set ND_Parent = ND_Source
Set ND = ND_Source
Do
If Cstr(ND.ParentDocumentUNID) = "" Then Exit Sub
Set ND = NDB.GetDocumentByUNID(ND.ParentDocumentUNID)
If Not ND Is Nothing Then
If Not ND_Parent Is ND Then
Call IsDocAccessed(ND, True)
Set ND_Parent = ND
Else
If ND_Parent Is ND_Source Then Set ND_Parent = Nothing
Exit Sub
End If
Else
On Error Goto 0
Exit Sub
End If
Loop
Exit Sub

Err4091:
Resume Next
End Sub
а потом для полученного ND_Parent вызываем TreeRDownC.
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
1
#5
пару вопросов-предположений :O_0:

почему не обрабатываем вариант наличия документа в коллекции проверкой наличия, а попускаем?
Код:
Sub TreeRDownC...
On Error 4469 Resume Next
...
Call NDC_Rez.AddDocument(ND) 
Call TreeRDownC(ND, NDC_Rez)
например так
Код:
On Error 4469 Resume Next
...
if NDC_Rez.GetDocument(ND) is nothing then
Call NDC_Rez.AddDocument(ND)
Call TreeRDownC(ND, NDC_Rez)
end if
вообще, я не вижу из приведенного кода, когда возможен вариант, что будет попытка добавить документ в коллекцию повторно (кроме как вызов извне на документе из дерева), но, логически будет верным вызывать TreeRDownC только для документов, которые в коллекцию добавлены в момент выполнения, иначе мы разрешаем ситуацию, когда дерево документов может быть обработато повторно, хотя изменений в коллекции произведено не будет. нет?


достаточно ли проверок
Код:
Function IsDocAccessed...

ND.IsValid And Not ND.IsDeleted
или может нужно еще и проверить доступность по доступу
Код:
ND.IsValid And Not ND.IsDeleted And isArray(ND.Items)
иначе можем получить в коллекции документ, с которым не получится работать.


лишний On Error или фича?
Код:
Sub GetTopDoc...
...
Else
On Error Goto 0
Exit Sub
End If
 

VladSh

начинающий
Lotus team
11.12.2009
1 262
6
#7
почему не обрабатываем вариант наличия документа в коллекции проверкой наличия, а попускаем?
Потому что проверка - это действие, на которое тратится время, а вероятность ошибки мала..

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

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

лишний On Error или фича?
On Error Goto 0
Exit Sub
Решил обнулить ошибку по человечески, т.к. Err=0 иногда всё равно выбивает, точно не помню, кажется в агентах на сервере.


Ещё косяк:
Функция IsDocAccessed может устанавливать ND в Nothing. В этом случае не сработает NDC.GetNextDocument(ND).
Это точно!
Поставлю здесь параметр в False.
EDITED: Посмотрел почему параметр в True - я сначала писал такие функции на массивы, так вот перебор доков там идёт по GetNthDocument, видимо код скопировал, а над параметром не задумался. И как оно уже столько лет работает?.. прикольно)))
Спасибо! Вот вместе и довели до ума :O_0:
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
1
#8
Массив полей появляется тогда, когда обе проверки проходят.
что имеется в виду под древними версиями? т.к. моя практика основывается на версиях 5-6, в 7-8 честно не проверял :O_0: и в них, если я не имею доступа к документу по РА-полям, но док каким-то образом получаю, то имею ситуацию, когда док валиден, не удален, но и итемсов нет О.о я только не помню как мы такие доки получали...

зы: буду рад переходу на "ты" :)
 

VladSh

начинающий
Lotus team
11.12.2009
1 262
6
#9
Akupaka
Ок, перейдём на "ты" :)
Стартовал с 5.03.. Есть привычка разные спорные (для меня) моменты перепроверять с выходом новой версии (а вдруг поправили? :) ). В 6.5.1 уже хватало 2-х проверок. Функции написаны и работают - ни разу не удалось получить док, чтобы проверки прошли, но Items бы не было; хотя может быть просто потому, что не ТУДА ещё не вступал.. :O_0:
Если вспомнится - напиши. Интересно, что это такое может быть..
 

hosm

* so what *
18.05.2009
2 442
6
#10
ND.IsValid And Not ND.IsDeleted
этих проверок достаточно. Проверки на массив айтемов - это наследие древних версий, когда нормально невозможно было проверить док. Массив полей появляется тогда, когда обе проверки проходят.
Будете смеяться?
Документ, к которому нет доступа:
Клиент - 7.0.3:
ND.IsValid = False IsEmpty(ND.Items) = True
Клиент - 8.5:
ND.IsValid = True IsEmpty(ND.Items) = True
сервер 7.0.3 - возможно, в этом причина?

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

VladSh

начинающий
Lotus team
11.12.2009
1 262
6
#11
OKEN, тут не до смеху...
Документ один и тот же???
Что говорит ND.IsDeleted?
 

hosm

* so what *
18.05.2009
2 442
6
#12
да не удален он, не удален. Админ (манагер) его получает без проблем. Валидным, неудаленным и с итемами.
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
1
#13
Добавлено: документ берется по униду
о! точно ))) надо док взять по униду! а я думаю, как же мы их получали? )))
это были проблемы у пользователей при работе со связанными документами, но когда к одному из них доступа нет, по какой-то причине, но унид был известен.
 

hosm

* so what *
18.05.2009
2 442
6
#14
Простую сделали форму: вводишь унид дока, и кнопочку, по которой коллега мне эту красоту и продемонстировал (в 2 клиентах под 2-мя id).
на досуге можешь глянуть корректность в 8.5.1. /*более "древняя" версия?*/ :)
В общем, вставляйте все проверки "на вшивость"...
 

VladSh

начинающий
Lotus team
11.12.2009
1 262
6
#15
Проверил лично, подтверждаю, всё что говорила выше OKEN! Раньше с этим не встречался, т.к. приложения были так спроектированы, что возникновение такой ситуации было исключено...
Откорректировал проверку в своей функции IsDocAccessed.

Т.к. обсуждение уже идёт по поводу какую проверку для этого лучше использовать :), то я предлагаю IsEmpty, т.к. проверка указанием на пустоту по аналогии с Object Is Nothing работает быстрее всего.
 

nvyush

Lotus team
22.04.2009
2 317
0
#16
ND.IsValid And Not ND.IsDeleted
Будете смеяться?
Документ, к которому нет доступа:
Клиент - 7.0.3:
ND.IsValid = False IsEmpty(ND.Items) = True
Клиент - 8.5:
ND.IsValid = True IsEmpty(ND.Items) = True
сервер 7.0.3 - возможно, в этом причина?

Добавлено: документ берется по униду, код один и тот же, клиент и сервер - английские.
А чему равен ND.Size? В моих проверках при открытии недоступного документа по UNID doc.Size = 0, doc.GetItemValue("AnyItem") и doc.AnyItem ошибку не генерят, ND.IsValid = False, ND.IsDeleted = False. Клиент 8.0.2ru, сервер 8.0.2.
Мне кажется, проверка на IsDeleted избыточна. В справке сказано, что она отражает текущее состояние объекта doc, а IsValid - при создании объекта. Таким образом, если мы делаем проверку сразу после set doc = db.GetDocumentByUnid, достаточно тестировать IsValid (если справка не врёт). Для дополнительной проверки ошибочно валидного документа в ситуации, приведённой OKEN, я предлагаю использовать проверку на doc.Size > 0, она будет быстрее IsEmpty(ND.Items). Если, конечно, в этой кривой ситуации и Size не "кривой". OKEN, есть возможность проверить?
 

hosm

* so what *
18.05.2009
2 442
6
#17
у меня ща нет времени - запарка жуткая, после 25го. и 8ки нет.
 
D

Darker

#18
По обходу документов-ответов: вчера на одном доке моя рекрсивная функция зациклилась.
Оказалось что-когда создается конфликт при галочке merge conflicts документ становится своим же потомком.
После этого решил сравнивать REF c UniversalID текущего дока
 

VladSh

начинающий
Lotus team
11.12.2009
1 262
6
#19
nvy
Хорошее решение! Осталось только определить, сколько времени занимает отработка метода Size... :)

Darker
Если можно, поподробнее:
- что за код зациклился?
- где изменили проверку?
 

ToxaRat

Чёрный маг
Lotus team
06.11.2007
3 231
18
#20
- что за код зациклился?
- где изменили проверку?
есть более злое решение :)

часто у меня возникает ситуация когда один документ становится респонсом на другой, который на деле является 20м потомком этого
поэтому пришлось в рекурсию еще и статистический счеткик ввести, чтобы рекурсия далья 255 колена обрывалась ;)