File: n_svc_dw_linkage.sru
Size: 18220
Date: Mon, 07 Apr 2008 21:31:07 +0200
$PBExportHeader$n_svc_dw_linkage.sru
$PBExportComments$Datawindow link service
forward
global type n_svc_dw_linkage from n_svc_dw
end type
end forward

global type n_svc_dw_linkage from n_svc_dw
end type
global n_svc_dw_linkage n_svc_dw_linkage

type variables

end variables

forward prototypes
public function integer of_setlink (ref n_svc_mgr anv_svc, readonly u_dw adw_requestor, ref str_dw_linkage astr)
public function integer of_preinsertrow (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr)
public function boolean of_iskeycolumn (readonly str_dw_linkage astr, readonly string as_colname)
public function integer of_getindex (readonly string as_array[], readonly string as_value)
public subroutine of_setredraw (readonly str_dw_linkage astr, readonly boolean ab)
public function integer of_setkeyvalues (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row)
public function integer of_itemfocuschanged (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row, readonly string as_column)
public subroutine of_retrievestart (ref str_dw_linkage astr)
public function integer of_insertrow (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row)
public function integer of_reset (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr)
public function integer of_rowfocuschanged (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row)
public function integer of_retrievedetails (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row)
public function integer of_refresh (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row)
public function integer of_findroot (readonly str_dw_linkage astr, ref u_dw adw)
public function integer of_rowfocuschanging (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_prevrow, readonly long al_newrow)
public function integer of_linkdetail (ref n_svc_mgr anv_svc, readonly u_dw adw_detail, ref str_dw_linkage astr)
public function integer of_retrieveend (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_rowcount)
public function integer of_itemchanged (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row, readonly string as_column, readonly string as_value)
public function integer of_keychanged (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row, readonly string as_column, readonly string as_oldvalue, readonly any aa_newvalue)
public function integer of_keysync (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row, readonly string as_column, readonly string as_oldvalue, readonly any aa_newvalue)
public function integer of_accepttext (readonly str_dw_linkage astr, readonly boolean ab_focusonerror)
public function integer of_save (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr)
public function integer of_validation (readonly str_dw_linkage astr)
end prototypes

public function integer of_setlink (ref n_svc_mgr anv_svc, readonly u_dw adw_requestor, ref str_dw_linkage astr);astr.dw_requestor = adw_requestor

windowobject lwo[]

n_svc_isempty lnv_check
n_svc_powerbuilder lnv_pb
long ll_count, n
boolean lb_found

anv_svc.of_LoadSvc(lnv_check, CSvc.ISEMPTY)
IF NOT lnv_check.of_IsEmpty(adw_requestor.#LinkMaster) THEN

   //check columns
   IF lnv_check.of_IsEmpty(adw_requestor.#MasterColumns) THEN 
      MessageBox(ClassName(), "No Master Column(s) specified for " + ClassName(adw_requestor) + ".", Exclamation!)
      RETURN CRet.FAILURE
   END IF
   IF lnv_check.of_IsEmpty(adw_requestor.#DetailColumns) THEN 
      MessageBox(ClassName(), "No Detail Column(s) specified for " + ClassName(adw_requestor) + ".", Exclamation!)
      RETURN CRet.FAILURE
   END IF

   anv_svc.of_LoadSvc(lnv_pb, CSvc.POWERBUILDER)
   ll_count = lnv_pb.of_GetWindowObjects(adw_requestor.GetParent(), lwo)
   FOR n = 1 to ll_count
      IF ClassName(lwo[n]) = adw_requestor.#LinkMaster THEN
         lb_found = TRUE
         EXIT
      END IF
   NEXT
   
   IF lb_found THEN     
      astr.dw_master = lwo[n]
      //ensure link
      astr.dw_master.of_SetLink(TRUE)

      //build columns
      n_svc_string lnv_str
      string ls_tmp1[], ls_tmp2[]
      long ll1, ll2
      string ls
      
      anv_svc.of_LoadSvc(lnv_str, CSvc.STRING)
      ll1 = lnv_str.of_ParseToArray(adw_requestor.#MasterColumns, &
         ",", ls_tmp1)
      ll2 = lnv_str.of_ParseToArray(adw_requestor.#DetailColumns, &
         ",", ls_tmp2)
      
      //count match?
      IF ll1 = 0 OR ll2 = 0 THEN 
         MessageBox(ClassName(), "No Master/Detail column count for " + ClassName(adw_requestor) + ".", Exclamation!)
         RETURN CRet.FAILURE
      END IF
      IF ll1 <> ll2 THEN 
         MessageBox(ClassName(), "Master/Detail column count mismatch for " + ClassName(adw_requestor) + ".", Exclamation!)
         RETURN CRet.FAILURE
      END IF
      
      //ensure columns exist
      //master
      ll_count = UPPERBOUND(ls_tmp1)
      FOR n = 1 to ll_count
         ls = of_GetColumnID(astr.dw_master, ls_tmp1[n])
         IF lnv_check.of_IsEmpty(ls) THEN 
            MessageBox(ClassName(), "Master column '" + ls_tmp1[n] + "' not found in " + ClassName(astr.dw_master) + ".", Exclamation!)
            RETURN CRet.FAILURE
         END IF
      NEXT
      //detail
      ll_count = UPPERBOUND(ls_tmp2)
      FOR n = 1 to ll_count
         ls = of_GetColumnID(adw_requestor, ls_tmp2[n])
         IF lnv_check.of_IsEmpty(ls) THEN 
            MessageBox(ClassName(), "Detail column '" + ls_tmp2[n] + "' not found in " + ClassName(adw_requestor) + ".", Exclamation!)
            RETURN CRet.FAILURE
         END IF
      NEXT
      
      //set columns
      astr.masterarg = ls_tmp1
      astr.detailarg = ls_tmp2
      
      //updateable?
      astr.IsUpdateable = adw_requestor.#Updateable
      astr.dw_master.of_LinkDetail(anv_svc, adw_requestor)
   ELSE
      RETURN CRet.FAILURE
   END IF
END IF

RETURN CRet.SUCCESS
end function

public function integer of_preinsertrow (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr);//TODO save logic

RETURN CRet.CONTINUE_ACTION
end function

public function boolean of_iskeycolumn (readonly str_dw_linkage astr, readonly string as_colname);long ll_count, n

ll_count = UPPERBOUND(astr.keycolumns)
FOR n = 1 to ll_count
   IF lower(astr.keycolumns[n]) = lower(as_colname) THEN RETURN TRUE
NEXT

RETURN FALSE
end function

public function integer of_getindex (readonly string as_array[], readonly string as_value);long ll_count, n

ll_count = UPPERBOUND(as_array)
FOR n = 1 to ll_count
   IF lower(as_array[n]) = lower(as_value) THEN RETURN n
NEXT

RETURN CRet.FAILURE
end function

public subroutine of_setredraw (readonly str_dw_linkage astr, readonly boolean ab);long ll_count, n

astr.dw_requestor.SetRedraw(ab)
ll_count = UPPERBOUND(astr.dw_detail)
FOR n = 1 to ll_count
   astr.dw_detail[n].SetRedraw(ab)
NEXT
end subroutine

public function integer of_setkeyvalues (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row);IF NOT ISVALID(astr.dw_requestor) THEN RETURN CRet.FAILURE
IF NOT ISVALID(astr.dw_master) THEN RETURN CRet.FAILURE

IF astr.dw_requestor.of_IsLinkRoot() THEN RETURN Cret.FAILURE

long ll_masterrow, ll_count, n
any la

ll_masterrow = astr.dw_master.GetRow()
IF ll_masterrow <= 0 THEN RETURN CRet.FAILURE

ll_count = UPPERBOUND(astr.masterarg)
FOR n = 1 to ll_count
   la = of_GetItemAny(astr.dw_master, ll_masterrow, astr.masterarg[n])
   of_SetItem(astr.dw_requestor, al_row, astr.detailarg[n], STRING(la))
NEXT

RETURN CRet.SUCCESS
end function

public function integer of_itemfocuschanged (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row, readonly string as_column);IF NOT ISVALID(astr.dw_requestor) THEN RETURN CRet.FAILURE

astr.Focuscolumn = as_column
astr.FocusValue = STRING(of_GetItemAny(astr.dw_requestor, al_row, astr.FocusColumn))

RETURN CRet.SUCCESS
end function

public subroutine of_retrievestart (ref str_dw_linkage astr);astr.IsRetrieving = TRUE
end subroutine

public function integer of_insertrow (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row);IF al_row = 0 THEN
   astr.IsInsertingRow = TRUE
   RETURN CRet.SUCCESS
END IF

astr.IsInsertingRow = FALSE

IF al_row > 0 AND al_row <> astr.dw_requestor.GetRow() THEN
   astr.dw_requestor.SetRow(al_row)
   astr.dw_requestor.ScrollToRow(al_row)
END IF

of_RowFocusChanged(anv_svc, astr, al_row)

RETURN of_SetKeyValues(anv_svc, astr, al_row)
end function

public function integer of_reset (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr);IF astr.dw_requestor.Reset() <> 1 THEN RETURN CRet.FAILURE

long ll_count, n, ll_ret

ll_count = UPPERBOUND(astr.dw_detail)
FOR n = 1 to ll_count
   ll_ret = of_Reset(anv_svc, astr.dw_detail[n].of_GetLinkDefinition())
   IF ll_ret <> 1 THEN EXIT
NEXT

RETURN ll_ret
end function

public function integer of_rowfocuschanged (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row);boolean  lb_preventfocuschanged
long ll_count, n, ll_row, ll_ret
long ll_priorrow

lb_preventfocuschanged = astr.preventfocuschange
astr.preventfocuschange = FALSE

ll_row = astr.dw_requestor.GetRow()
IF ISNULL(ll_row) THEN RETURN CRet.FAILURE

IF lb_preventfocuschanged THEN RETURN CRet.FAILURE

ll_count = UPPERBOUND(astr.dw_detail)

dwitemstatus ldwi

FOR n = 1 to ll_count
   IF ll_row <= 0 THEN
      of_Reset(anv_svc, astr.dw_detail[n].of_GetLinkDefinition())
      CONTINUE
   ELSE
      ldwi = astr.dw_requestor.GetItemStatus(al_row, 0, Primary!)
      
      IF ldwi = New! OR ldwi = NewModified! THEN
         of_Reset(anv_svc, astr.dw_detail[n].of_GetLinkDefinition())
      END IF
   END IF
   
   //refresh
   ll_ret = of_Refresh(anv_svc, astr.dw_detail[n].of_GetLinkDefinition(), ll_row)
   IF ll_ret < 0 THEN
      astr.dw_requestor.SetRow(ll_priorrow)
      astr.dw_requestor.ScrollToRow(ll_priorrow)
   ELSE
      ll_priorrow = astr.dw_requestor.GetRow()
   END IF
NEXT

RETURN CRet.SUCCESS
end function

public function integer of_retrievedetails (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row);long ll_ret, ll_count, n
any la_args[20], la
boolean lb_retrieve

IF astr.dw_requestor.of_IsLinkRoot() THEN RETURN CRet.FAILURE
IF NOT ISVALID(astr.dw_master) THEN RETURN CRet.FAILURE

IF ISNULL(al_row) OR al_row <= 0 THEN RETURN CRet.FAILURE

dwitemstatus ldwi

ldwi = astr.dw_master.GetItemStatus(al_row, 0, Primary!)

IF ldwi = New! OR ldwi = NewModified! THEN
   of_Reset(anv_svc, astr)
   RETURN CRet.SUCCESS
END IF

ll_count = UPPERBOUND(astr.masterarg)
FOR n = 1 to ll_count
   la_args[n] = of_GetItemAny(astr.dw_master, al_row, astr.masterarg[n])
   
   IF NOT lb_retrieve THEN
      IF astr.dw_requestor.RowCount() = 0 THEN
         lb_retrieve = TRUE
      ELSEIF astr.dw_requestor.ModifiedCount() > 0 OR astr.dw_requestor.DeletedCount() > 0 THEN
         lb_retrieve = TRUE
      ELSE
         la = of_GetItemAny(astr.dw_requestor, 1, astr.detailarg[n])
         
         IF ISNULL(la) OR ISNULL(la_args[n]) THEN
            lb_retrieve = TRUE
         ELSEIF la_args[n] <> la THEN
            lb_retrieve = TRUE
         END IF
      END IF
   END IF
NEXT

IF NOT lb_Retrieve THEN
   RETURN CRet.SUCCESS
END IF

ll_ret = astr.dw_requestor.of_Retrieve(la_args)

IF ll_ret > 0 THEN
   //TODO rowchanged
END IF

RETURN ll_ret
end function

public function integer of_refresh (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row);IF astr.dw_requestor.of_IsLinkRoot() THEN RETURN CRet.FAILURE

u_dw ldw

IF of_FindRoot(astr, ldw) <> CRet.SUCCESS THEN RETURN CRet.FAILURE

RETURN of_RetrieveDetails(anv_svc, astr, al_row)
end function

public function integer of_findroot (readonly str_dw_linkage astr, ref u_dw adw);integer li_ret

IF astr.dw_requestor.of_IsLinkRoot() THEN
   adw = astr.dw_requestor
   RETURN CRet.SUCCESS
END IF

IF NOT ISVALID(astr.dw_master) THEN RETURN CRet.FAILURE

li_ret = of_FindRoot(astr.dw_master.of_GetLinkDefinition(), adw)

RETURN li_ret
end function

public function integer of_rowfocuschanging (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_prevrow, readonly long al_newrow);boolean  lb_allowfocuschange

IF NOT astr.dw_requestor.of_IsLinkMaster() THEN RETURN CRet.CONTINUE_ACTION

lb_allowfocuschange = astr.allowfocuschange
astr.allowfocuschange = FALSE

IF astr.IsInsertingRow THEN RETURN CRet.CONTINUE_ACTION
IF astr.IsRetrieving THEN RETURN CRet.CONTINUE_ACTION
IF astr.dw_requestor.DeletedCount() > 0 THEN RETURN CRet.CONTINUE_ACTION
IF lb_allowfocuschange THEN RETURN CRet.CONTINUE_ACTION
IF astr.dw_requestor.RowCount() + astr.dw_requestor.FilteredCount() <= 0 THEN RETURN CRet.CONTINUE_ACTION

//TODO Save
IF of_Save(anv_svc, astr) = CRet.FAILURE THEN RETURN CRet.PREVENT_ACTION

RETURN CRet.CONTINUE_ACTION
end function

public function integer of_linkdetail (ref n_svc_mgr anv_svc, readonly u_dw adw_detail, ref str_dw_linkage astr);long ll_upper, ll_count, n, m
str_dw_linkage lstr
boolean lb_found

IF NOT ISVALID(adw_detail) THEN RETURN CRet.FAILURE

lstr = adw_detail.of_GetLinkDefinition()

//add detail
ll_upper = UPPERBOUND(astr.dw_detail) + 1
astr.dw_detail[ll_upper] = adw_detail

//add keycolumns
ll_count = UPPERBOUND(lstr.detailarg)
ll_upper = UPPERBOUND(astr.KeyColumns)
FOR m = 1 to ll_count
   lb_found = FALSE
   FOR n = 1 to ll_upper
      IF astr.KeyColumns[n] = lstr.detailarg[m] THEN
         lb_found = TRUE
         EXIT
      END IF
   NEXT
   IF NOT lb_found THEN
      astr.KeyColumns[UPPERBOUND(astr.KeyColumns) + 1] = lstr.masterarg[m]
   END IF
NEXT

RETURN CRet.SUCCESS
end function

public function integer of_retrieveend (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_rowcount);of_ItemFocusChanged(anv_svc, astr, astr.dw_requestor.GetRow(), astr.dw_requestor.GetColumnName())

astr.IsRetrieving = FALSE

IF al_rowcount > 0 THEN
   astr.dw_requestor.EVENT rowfocuschanged(1)
END IF

RETURN CRet.SUCCESS
end function

public function integer of_itemchanged (ref n_svc_mgr anv_svc, ref str_dw_linkage astr, readonly long al_row, readonly string as_column, readonly string as_value);IF NOT ISVALID(astr.dw_requestor) THEN RETURN CRet.FAILURE

IF NOT of_IsKeyColumn(astr, as_column) THEN RETURN CRet.NO_ACTION

IF as_column <> astr.focuscolumn THEN RETURN CRet.FAILURE

//ensure value
of_SetItem(astr.dw_requestor, al_row, as_column, as_value)

//get new value
any la
la = of_GetItemAny(astr.dw_requestor, al_row, as_column)

of_SetRedraw(astr, FALSE)
of_KeyChanged(anv_svc, astr, al_row, as_column, astr.focusvalue, la)
of_SetRedraw(astr, TRUE)

//set new value
astr.focusvalue = astr.dw_requestor.GetText()

RETURN CRet.SUCCESS
end function

public function integer of_keychanged (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row, readonly string as_column, readonly string as_oldvalue, readonly any aa_newvalue);long ll_dwcount, n, ll_ret

IF NOT ISVALID(astr.dw_requestor) THEN RETURN CRet.FAILURE
IF al_row < 0 THEN RETURN CRet.FAILURE
IF ISNULL(as_column) OR TRIM(as_column) = CString.EMPTY THEN RETURN CRet.FAILURE

ll_dwcount = UPPERBOUND(astr.dw_detail)
FOR n = 1 to ll_dwcount
   ll_ret = of_KeySync(anv_svc, astr.dw_detail[n].of_GetLinkDefinition(), al_row, as_column, as_oldvalue, aa_newvalue)
   IF ll_ret < 0 THEN RETURN CRet.FAILURE
NEXT

RETURN CRet.SUCCESS
end function

public function integer of_keysync (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr, readonly long al_row, readonly string as_column, readonly string as_oldvalue, readonly any aa_newvalue);long ll_idx, n, ll_count, ll_find, ll_rowcount
any la
string ls_find, ls_detailcol, ls_value, ls_expression
str_dw_linkage lstr
boolean lb_iskey
n_svc_isempty lnv_check

IF NOT ISVALID(astr.dw_requestor) THEN RETURN CRet.FAILURE

ll_idx = of_GetIndex(astr.masterarg, as_column)

IF ll_idx = CRet.FAILURE THEN RETURN CRet.NO_ACTION

ls_detailcol = astr.detailarg[ll_idx]

lb_iskey = of_IsKeycolumn(astr, ls_detailcol)

anv_svc.of_LoadSvc(lnv_check, CSvc.ISEMPTY)

ll_count = UPPERBOUND(astr.masterarg)
FOR n = 1 to ll_count
   IF lower(astr.masterarg[n]) = lower(as_column) THEN
      ls_value = as_oldvalue
   ELSE
      ls_value = STRING(of_GetItemAny(astr.dw_master, al_row, astr.masterarg[n]))
   END IF
   
   //make expression
   ls_expression = of_BuildColumnValueString(anv_svc, astr.dw_requestor, astr.detailarg[n], ls_value, FALSE)
   
   IF lnv_check.of_IsEmpty(ls_expression) THEN CONTINUE
   
   IF NOT lnv_check.of_IsEmpty(ls_find) THEN ls_find += " AND "
   
   ls_find += ls_expression
NEXT

ll_rowcount = astr.dw_requestor.RowCount()
DO
   ll_find = astr.dw_requestor.Find(ls_find, 1, ll_rowcount)
   IF ll_find > 0 THEN
      //of_SetItem(astr.dw_requestor, ll_find, ls_detailcol, STRING(aa_newvalue))
      of_SetItem(astr.dw_requestor, ll_find, ls_detailcol, STRING(aa_newvalue))
      
      IF lb_iskey THEN
         of_KeyChanged(anv_svc, astr, ll_find, ls_detailcol, as_oldvalue, aa_newvalue)
      END IF
   END IF
LOOP WHIlE ll_find > 0

RETURN CRet.SUCCESS
end function

public function integer of_accepttext (readonly str_dw_linkage astr, readonly boolean ab_focusonerror);IF NOT ISVALID(astr.dw_requestor) THEN RETURN CRet.FAILURE

IF astr.dw_Requestor.EVENT ke_accepttext(ab_focusonerror) <> 1 THEN
   RETURN CRet.FAILURE
END IF

long ll_count, n

ll_count = UPPERBOUND(astr.dw_detail)
FOR n = 1 to ll_count
   IF of_AcceptText(astr.dw_detail[n].of_GetLinkDefinition(), ab_focusonerror) <> CRet.SUCCESS THEN
      RETURN CRet.FAILURE
   END IF
NEXT

RETURN CRet.SUCCESS
end function

public function integer of_save (ref n_svc_mgr anv_svc, readonly str_dw_linkage astr);IF of_Validation(astr) = CRet.FAILURE THEN RETURN CRet.FAILURE

RETURN CRet.SUCCESS
end function

public function integer of_validation (readonly str_dw_linkage astr);IF astr.dw_requestor.EVENT ke_linkagevalidate() = CRet.FAILURE THEN 
   astr.dw_requestor.POST SetFocus()
   RETURN CRet.FAILURE
END IF

long ll_count, n

ll_count = UPPERBOUND(astr.dw_detail)
FOR n = 1 to ll_count
   IF of_Validation(astr.dw_detail[n].of_GetLinkDefinition()) = CRet.FAILURE THEN RETURN CRet.FAILURE
NEXT

RETURN CRet.SUCCESS
end function

on n_svc_dw_linkage.create
call super::create
end on

on n_svc_dw_linkage.destroy
call super::destroy
end on