CREATE OR REPLACE PACKAGE BODY SnapshotMXS AS SOURCE NUMBER(1):= 0; TARGET NUMBER(1):= 1; ELEMENT NUMBER(1):= 0; ASSOC NUMBER(1):= 1; MDL_MODE NUMBER(1):= 0; DEFAULT_STRATEGY_TURNED_OFF NUMBER(1) := 0; DEFAULT_STRATEGY_TURNED_ON NUMBER(1) := 1; type rType is record ( srcID cmpelement_v.elementid%TYPE, tgtID cmpelement_v.elementid%TYPE ); type matchType is table of rType index by BINARY_INTEGER; matchTable matchType; type idType is table of lwcontext.elementid%TYPE index by BINARY_INTEGER; type qualType is table of lwcontext.diffcol%TYPE index by BINARY_INTEGER; type rowidType is table of VARCHAR2(2000) index by BINARY_INTEGER; type uoidType is table of lwcontext.uoid%TYPE index by BINARY_INTEGER; /* PROCEDURE testWrite(id IN NUMBER) IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN insert into t values(id); commit; END; PROCEDURE testWrite2(before IN NUMBER,numRows IN NUMBER) IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN insert into t2(elementid,type) values (before,numRows); commit; END; PROCEDURE testWrite3(before IN NUMBER) IS PRAGMA AUTONOMOUS_TRANSACTION; BEGIN insert into t2 select tmp.*,before from lwcontexttemp tmp; commit; END; */ FUNCTION getFirstClassObject(elemID IN NUMBER) RETURN NUMBER IS vElemID cmpelement_v.elementid%TYPE; cursor c is select firstclassobject from secondclassobject_v where elementid = elemID; BEGIN open c; fetch c into vElemID; if (c%NOTFOUND) then return elemID; end if; return vElemID; END getFirstClassObject; FUNCTION getValidBoundary(elemID IN NUMBER) RETURN NUMBER IS BEGIN if (Snapshot.isFirstClassObject(elemID)) then return elemID; end if; if (Snapshot.isSecondClassObject(elemID)) then return getFirstClassObject(elemID); end if; return elemID; END getValidBoundary; FUNCTION isInComponentBoundary(elemID IN NUMBER) RETURN BOOLEAN IS BEGIN Snapshot.debug('SnapshotMXS.isInComponentBoundary: elemID = ',elemID); if (Snapshot.isFirstClassObject(elemID)) then return TRUE; end if; if (Snapshot.isSecondClassObject(elemID)) then return TRUE; end if; return FALSE; END isInComponentBoundary; /** * Reads from the pctree and creates a string that contains a list of * physical names of the object * @param elemID element id of the object whose fully qualified name * you would want * @param boundaryID the elementid of the object parent at * which the naming should start */ FUNCTION getQualifiedName(elemID IN NUMBER,boundaryID IN NUMBER,objType IN NUMBER) RETURN VARCHAR2 IS fullName VARCHAR2(1000):= ''; seq NUMBER(2); vName cmpelement_v.name%TYPE; vClassName cmpelement_v.classname%TYPE; componentBoundary cmpelement_v.elementid%TYPE; numRows cmpelement_v.elementid%TYPE:= 0; BEGIN BEGIN select ordering into seq from hierarchytable h where h.rootid = elemID and h.memberID = boundaryID; Snapshot.debug('SnapshotMXS.getQualifiedName: seq = ' || seq || ' rootid = ' || elemID || ' boundaryID = ',boundaryID); EXCEPTION when NO_DATA_FOUND then if (isInComponentBoundary(elemID)) then componentBoundary:= getValidBoundary(elemID); BEGIN select ordering into seq from hierarchytable h where h.rootid = elemID and h.memberID = componentBoundary; EXCEPTION when NO_DATA_FOUND then return '/'; END; elsif (objtype = Snapshot.LOGICAL) then select classname, name into vClassName, vName from cmpelement_v where elementid = elemID; else select classname, logicalname into vClassName, vName from cmpelement_v where elementid = elemID; end if; return '/' || vName || '/' || vClassName; END; for c in (select cmp.name,cmp.className,cmp.elementid from hierarchytable h,cmpelement_v cmp where h.rootid = elemID and cmp.elementid = h.memberid and h.ordering <= seq) loop fullName:= fullName || '/' || c.name || '/' || c.className; numRows:= numRows+1; end loop; return fullName; END; /** * Reads from the pctree and creates a string that contains a list of * physical names of the object * @param elemID element id of the object whose fully qualified name * you would want * @param boundaryID the elementid of the object parent at * which the naming should start */ FUNCTION getQualifiedPosition(elemID IN NUMBER,boundaryID IN NUMBER) RETURN VARCHAR2 IS fullName VARCHAR2(1000):= ''; seq NUMBER(2); vName cmpelement_v.name%TYPE; vPosition cmpattribute_v.position%TYPE; vPositionStr VARCHAR2(4000); vClassName cmpelement_v.classname%TYPE; componentBoundary cmpelement_v.elementid%TYPE; numRows cmpelement_v.elementid%TYPE:= 0; BEGIN BEGIN select ordering into seq from hierarchytable h where h.rootid = elemID and h.memberID = boundaryID; Snapshot.debug('SnapshotMXS.getQualifiedPosition: elemID= ',elemID); Snapshot.debug('SnapshotMXS.getQualifiedPosition: seq= ',seq); EXCEPTION when NO_DATA_FOUND then if (isInComponentBoundary(elemID)) then componentBoundary:= getValidBoundary(elemID); BEGIN select ordering into seq from hierarchytable h where h.rootid = elemID and h.memberID = componentBoundary; EXCEPTION when NO_DATA_FOUND then return '/'; END; else select classname, name into vClassName, vName from cmpelement_v where elementid = elemID; return '/' || vName || '/' || vClassName; end if; END; for c in (select h.memberid elementid,cmp.name,cmp.classname from hierarchytable h,cmpelement_v cmp where h.rootid = elemID and h.ordering <= seq and cmp.elementid = h.memberid) loop Snapshot.debug('SnapshotMXS.getQualifiedPosition: c.elementid = ',c.elementid); Snapshot.debug('SnapshotMXS.getQualifiedPosition: c.name = ',c.name); Snapshot.debug('SnapshotMXS.getQualifiedPosition: c.classname = ',c.classname); BEGIN select position into vPosition from cmpattribute_v where elementid = c.elementid; Snapshot.debug('SnapshotMXS.getQualifiedPosition: has position value = ',vPosition); vPositionStr:= TO_CHAR(vPosition); EXCEPTION when NO_DATA_FOUND then vPositionStr:= c.name; Snapshot.debug('SnapshotMXS.getQualifiedPosition: no position value ',vPositionStr); END; Snapshot.debug('SnapshotMXS.getQualifiedPosition: has position vPosition ',vPositionStr); fullName:= fullName || '/' || vPositionStr || '/' || c.classname; Snapshot.debug('SnapshotMXS.getQualifiedPosition: fullName =',fullName); numRows:= numRows+1; end loop; return fullName; END getQualifiedPosition; FUNCTION getQualifier(nameORpos IN NUMBER,elemID IN NUMBER, boundaryID IN NUMBER,objType IN NUMBER) RETURN VARCHAR2 IS BEGIN if (nameORpos = Snapshot.NAMEBASED) then return getQualifiedName(elemID,boundaryID,objType); end if; if (nameORpos = Snapshot.POSBASED) then return getQualifiedPosition(elemID,boundaryID); end if; return getQualifiedName(elemID,boundaryID,objType); END getQualifier; PROCEDURE syncPCAssociations(snap IN NUMBER) IS BEGIN update lwcontexttemp lw set assoccol = ( select diffcol from lwcontexttemp where elementid = lw.associd and snapshotid = snap and assoctype = Snapshot.PARENT_ASSOC ) where snapshotid = snap and assoctype = Snapshot.PARENT_ASSOC; update lwcontexttemp lw set diffcol = ( select diffcol from lwcontexttemp where elementid = lw.elementid and snapshotid = snap and assoctype = Snapshot.PARENT_ASSOC ) where snapshotid = snap and ( assoctype = Snapshot.INTRA_ASSOC or assoctype = Snapshot.INTER_ASSOC ); END syncPCAssociations; /** * This changes the matching strategies for certain associations based * on the MCMSemantics table * @param elemID component element id * @param snap snapshot id */ PROCEDURE customizeMatchingStrategies(elemID IN NUMBER,snap IN NUMBER) IS qualRowID rowidType; deleteAssocID rowIDType; qualAttr qualType; qualAssocAttr qualType; i BINARY_INTEGER:= 0; j BINARY_INTEGER:= 0; k BINARY_INTEGER:= 0; BEGIN /* if (Snapshot.isDebug()) then for c in (select distinct lw.snapshotid,lw.uoid,lw.physicalname,lw.elementid, lw.objtype,lw.assocuoid,lw.diffcol,lw.assoccol, lw.associd,m.matchingstrategy,m.linktype,lw.role,lw.assocrole, lw.classname,lw.assocclassname,lw.assoctype from lwcontexttemp lw,mcmsemantics m where lw.classname = m.tolinkclass and lw.role = m.tolinkrole and lw.assocrole = m.fromlinkrole and m.matchingstrategy != Snapshot.UOIDBASED and lw.snapshotid = snap) loop Snapshot.debug('name = ' || c.physicalname || ' snapshotid = ' || c.snapshotid || ' elementid = ' || c.elementid || ' associd = ' || c.associd || ' role = ' || c.role || ' assocrole = ' || c.assocrole || ' uoid = ' || c.uoid || ' assocuoid = ' || c.assocuoid || ' diffcol = ' || c.diffcol || ' assoccol = ' || c.assoccol || ' assocType = ' || c.assoctype,''); end loop; for c in (select * from mcmsemantics) loop Snapshot.debug('linktype = ' || c.linktype || ' fromlinkclass = ' || c.fromlinkclass || ' fromlinkrole = ' || c.fromlinkrole || ' tolinkclass = ' || c.tolinkclass ||' tolinkrole = ' || c.tolinkrole || ' matchingstrategy = ' || c.matchingstrategy,''); end loop; end if; */ for c in (select lw.rowid,lw.elementid,lw.objtype, lw.associd,m.matchingstrategy,m.linktype,lw.role,lw.assocrole, lw.classname,lw.assocclassname,lw.assoctype from lwcontexttemp lw,mcmsemantics m where lw.classname = m.tolinkclass and lw.role = m.tolinkrole and lw.assocrole = m.fromlinkrole and lw.snapshotid = snap) loop if (c.matchingstrategy = Snapshot.UOIDBASED) then null; elsif (c.matchingstrategy = Snapshot.IGNORE) then deleteAssocID(k):= c.rowid; k:= k+1; Snapshot.debug('SnapshotMXS.customizeMatchingStrategies: deleted associations for snapshotid = ',snap); Snapshot.debug('elementid = ' || c.elementid || ' role = ' || c.role || ' assocrole = ' || c.assocrole || ' classname = ' || c.classname || ' assocclassname = ' || c.assocclassname || ' assoctype = ' || c.assoctype,''); else qualRowID(j):= c.rowid; qualAttr(j):= getQualifier(c.matchingstrategy,c.elementid,elemID,c.objtype); if (c.associd is null) then qualAssocAttr(j):= 'null'; else qualAssocAttr(j):= getQualifier(c.matchingstrategy,c.associd,elemID,c.objtype); end if; j:= j+1; end if; end loop; forall indx in 0..j-1 update lwcontexttemp set diffcol = qualAttr(indx),assoccol = qualAssocAttr(indx) where rowid = qualRowID(indx); forall indx in 0..k-1 delete from lwcontexttemp where rowid = deleteAssocID(indx); Snapshot.debug('SnapshotMXS.customizeMatchingStrategies: ','after updating matching strategy'); if (Snapshot.isDebug()) then for c in (select * from lwcontexttemp where snapshotid = snap) loop Snapshot.debug('name = ' || c.physicalname || ' snapshotid = ' || c.snapshotid || ' elementid = ' || c.elementid || ' associd = ' || c.associd || ' role = ' || c.role || ' assocrole = ' || c.assocrole || ' uoid = ' || c.uoid || ' assocuoid = ' || c.assocuoid || ' diffcol = ' || c.diffcol || ' assoccol = ' || c.assoccol || ' assocPhysName = ' || c.assocphysname || ' assocType = ' || c.assoctype,''); end loop; end if; END customizeMatchingStrategies; PROCEDURE reconcileTransientUOIDs IS rowidList rowidType; uoidList uoidType; classnameList uoidType; assocclassnameList uoidType; roleList uoidType; assocroleList uoidType; idList idType; i BINARY_INTEGER:= 0; j BINARY_INTEGER:= 0; BEGIN for i in 0..matchTable.COUNT-1 loop Snapshot.debug('SnapshotMXS.reconcileTransientUOIDs: matchTable(i).srcID = ',matchTable(i).srcID); Snapshot.debug('SnapshotMXS.reconcileTransientUOIDs: matchTable(i).tgtID = ',matchTable(i).tgtID); for c in (select distinct a.rowid,b.elementid,a.uoid,a.classname,a.role, a.assocclassname,a.assocrole from interlink i, interlink j, ( select uoid,elementid,classname,role,assocclassname,assocrole from lwcontexttemp where rootid = matchTable(i).srcID ) a, ( select uoid,elementid from lwcontexttemp where rootid = matchTable(i).tgtID ) b, mcmsemantics m where a.elementid = i.linkfrom and b.elementid = j.linkfrom and i.linkto = j.linkto and a.assocclassname = m.fromlinkclass and a.assocrole = m.fromlinkrole and a.classname = m.tolinkclass and a.role = m.tolinkrole and m.matchingstrategy = Snapshot.UOIDBASED) loop Snapshot.debug('SnapshotMXS.reconcileTransientUOIDs: updating elementid = ' || c.elementid || ' to uoid ',c.uoid); Snapshot.debug('SnapshotMXS.reconcileTransientUOIDs: processing association ' || c.classname || ' ' || c.role || ' ' || c.assocclassname || ' ' || c.assocrole,''); select rowid into rowidList(j) from lwcontexttemp where elementid = c.elementid and classname = c.classname and role = c.role and assocclassname = c.assocclassname and assocrole = c.assocrole; uoidList(j):= c.uoid; j:= j+1; end loop; end loop; forall indx in 0..j-1 update lwcontexttemp set diffcol = uoidList(indx) where rowid = rowidList(indx); END reconcileTransientUOIDs; PROCEDURE takeTransientSnapshot(elemID IN NUMBER,type IN NUMBER, labelStr IN VARCHAR2) IS snap cmpelement_v.elementid%TYPE; BEGIN Snapshot.storeComponentRows(elemID,Snapshot.CASCADE_SNAPSHOT, Snapshot.CURRENT_SNAPSHOT); snap:= Snapshot.getSnapshotID(labelStr,Snapshot.TRANSIENT_SNAPSHOT,'',Snapshot.LIGHT_SNAPSHOT); Snapshot.debug('SnapshotMXS.takeTransientSnapshot: snap = ',snap); Snapshot.takeLWSnapshot(elemID,snap,Snapshot.TRANSIENT_SNAPSHOT, Snapshot.CURRENT_SNAPSHOT); customizeMatchingStrategies(elemID,snap); Snapshot.cleanTempTable(); END takeTransientSnapshot; /** * This allows the user to take snapshots on multiple objects. * The client must first insert into the MCMComponent table the following info: * * element id in elementid column of mcmcomponent * 0/1 in the type column (0 for SOURCE, 1 for TARGET) of mcmcomponent * Note that the source row should always come before the target row, and that * the source matched to the target are to come after each other * * @param isMDL parameter passed from the client to know if this is * being invoked by MDL * @return snapName the generated snapshot names (src | target) to * be used by the compare */ FUNCTION takeTransientSnapshots(isMDL IN NUMBER) RETURN VARCHAR2 IS elemID1 cmpelement_v.elementid%TYPE; elemID2 cmpelement_v.elementid%TYPE; snapName1 snapshotlookup.snapshotname%TYPE; snapName2 snapshotlookup.snapshotname%TYPE; i BINARY_INTEGER:= 0; done BOOLEAN:= FALSE; snap snapshotlookup.snapshotid%TYPE; BEGIN --if (NOT(ServerLog.isOpen())) then -- ServerLog.open('e:\work\mcm','log.txt'); --end if; --if (NOT(ServerLog.isOpen())) then -- ServerLog.open('d:\temp','Snapshot.log'); --end if; delete from lwcontexttemp; select cwmseq.nextval into elemID1 from dual; select cwmseq.nextval into elemID2 from dual; snapName1:= TO_CHAR(elemID1); snapName2:= TO_CHAR(elemID2); for c in (select elementid,type from mcmcomponent) loop if (c.type = SOURCE) then takeTransientSnapshot(c.elementid,c.type,snapName1); matchTable(i).srcID:= c.elementid; if (done) then i:= i+1; else done:= TRUE; end if; else takeTransientSnapshot(c.elementid,c.type,snapName2); matchTable(i).tgtID:= c.elementid; if (done) then i:= i+1; else done:= TRUE; end if; end if; end loop; Snapshot.cleanComponent(); if (NOT(isMDL = MDL_MODE)) then Snapshot.debug('SnapshotMXS.takeTransientSnapshots: ','link reconciliation'); reconcileTransientUOIDs(); end if; snap:= Snapshot.getSnapshotID(snapName1,Snapshot.TRANSIENT_SNAPSHOT,'',Snapshot.LIGHT_SNAPSHOT); syncPCAssociations(snap); snap:= Snapshot.getSnapshotID(snapName2,Snapshot.TRANSIENT_SNAPSHOT,'',Snapshot.LIGHT_SNAPSHOT); syncPCAssociations(snap); --For Paris, CMPAllClasses has been split into multiple base tables, so do this... --delete from cmpallclasses where b_6 = 0; delete from CMPFCOClasses where b_6 = 0; --delete from CMPMMMClasses where b_6 = 0; delete from CMPSCOClasses where b_6 = 0; delete from CMPSCOCfgClasses where b_6 = 0; delete from CMPSCOMapClasses where b_6 = 0; delete from CMPSCOPrpClasses where b_6 = 0; delete from CMPSYSClasses where b_6 = 0; delete from mcmsemantics; if (Snapshot.isDebug()) then for c in (select * from lwcontexttemp) loop Snapshot.debug('name = ' || c.physicalname || ' snapshotid = ' || c.snapshotid || ' elementid = ' || c.elementid || ' associd = ' || c.associd || ' role = ' || c.role || ' assocrole = ' || c.assocrole || ' uoid = ' || c.uoid || ' assocuoid = ' || c.assocuoid || ' diffcol = ' || c.diffcol || ' assoccol = ' || c.assoccol || ' assocPhysName = ' || c.assocphysname || ' assocType = ' || c.assoctype,''); end loop; end if; --ServerLog.close(); return snapName1 || '|' || snapName2; END; END SnapshotMXS; /