陈清红
2025-04-14 880f3c0257eeb8c37761d484258fdd102a369a19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
Quintiq file version 2.0
#parent: #root
Method MessageReceiveSetUpdated (String messageType_i, NamedValueTree nvt_i)
{
  Description: 'Handle and process the message received of type set updated'
  TextBody:
  [*
    sourceKind := LibInt_MessageAccessor::GetHeaderPropertyAsString( nvt_i, LibDMF_CommunicationChannel::HEADER_SOURCEKIND() );
    sourceName := LibInt_MessageAccessor::GetHeaderPropertyAsString( nvt_i, LibDMF_CommunicationChannel::HEADER_SOURCENAME() );
    
    // LastUpdated can be missing when the message is received from an IF-system.
    lastUpdated := ifexpr( LibInt_MessageAccessor::HasHeaderProperty( nvt_i, LibDMF_CommunicationChannel::HEADER_LAST_UPDATED() ),
                           LibInt_MessageAccessor::GetHeaderPropertyAsDateTime( nvt_i, LibDMF_CommunicationChannel::HEADER_LAST_UPDATED() ),
                           DateTime::MinDateTime() );
    
    // The message might have been sent in response to a Request; in that case the header contains a RequestID.
    requestID := ifexpr( LibInt_MessageAccessor::HasHeaderProperty( nvt_i, LibDMF_CommunicationChannel::HEADER_REQUESTID() ),
                         LibInt_MessageAccessor::GetHeaderPropertyAsString( nvt_i, LibDMF_CommunicationChannel::HEADER_REQUESTID() ),
                         LibDMF_CommunicationChannel::REQUEST_NO_ID() );
    
    root := this.CommunicationChannelRoot();
    
    // Retrieve IntegrationEvent.
    event := root.EventGetLast( sourceKind, sourceName );
    
    // Log the Activity
    root.EventLogActivity( event, "Instantiate data" );
    
    if( this.CommunicationChannelRoot().IsDataManager() )
    {
      set := this.GetSet( nvt_i, true );
    
      if( not isnull( set ) )
      {
        // TODO: send error message if set/set type not found or not owned by SoC
    
        this.DataInstantiateInChannelOfDataManager( nvt_i, set );
    
        // If applicable, check for cycles; this is part of the Primary Sanity Check.
        if( this.IsHierarchyChannel() )
        {
          set.CheckHierarchyIsCyclic();
    
          feedbacks := construct( Strings );
          if( not set.GetHasAcyclicHierarchy( feedbacks ) )
          {
            // Raise an error in order to have the transaction rolled back and revert the original data.
            feedback := "";
            LibDMF_Util::FeedbacksToString( this.CommunicationChannelRoot(), false, feedbacks, feedback );
    
            root.EventLogActivityError( event,
                                        "Set [" + set.Name() + "] contains a cyclic hierarchy.",
                                        feedback );
          }
        }
    
        // Check if the data is 'sane' and can be send to Systems that are interested in it.
        feedbacks := construct( Strings );
        canSend   := set.DoSanityCheck( feedbacks );
    
        if( canSend )
        {
          // End of event (for Interface System messages)
          root.EventComplete( event );
    
          // Send the data to the Systems that are interested in it.
          set.SendToInterestedSystems( messageType_i );
        }
        else
        {
          root.EventLogActivityWarning( event,
                                        "Cannot send data to interested Systems. Reason(s) :" + String::NewLine() + feedbacks.Concatenate( String::NewLine() ) );
        }
      }
    }
    else
    {
      data := this.DataInstantiateInChannelOfSystem( nvt_i );
    
      // In a System the generic data must be transformed into the target data structure.
      activityInfo := ifexpr( requestID <> LibDMF_CommunicationChannel::REQUEST_NO_ID(), ", RequestID = " + requestID, "" );
      root.EventLogActivity( event, "Synchronize data" + activityInfo );
    
      // Provide the RequestID to the System so it can take action on it if required.
      this.DataSynchronizeToSystem( data, lastUpdated, requestID );
    
      // The data in the Channel can be deleted again.
      traverse( data, Elements, object )
      {
        object.Delete();
      }
    }
  *]
}