1 /*=========================================================================
2  *
3  *  Copyright NumFOCUS
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 /*
19 basically, given an initial byte, construct the appropriate PDU.
20 this way, the event loop doesn't have to know about all the different PDU types.
21 
22 name and date: 25 Sept 2010 mmr
23 
24 Updte on 27 sept 2010 mmr: since this is where all PDUs are included, also use this
25 class to construct specific instances of PDUs, and return the BasePDU class.
26 */
27 #include "gdcmPDUFactory.h"
28 #include "gdcmAAbortPDU.h"
29 #include "gdcmAAssociateACPDU.h"
30 #include "gdcmAAssociateRJPDU.h"
31 #include "gdcmAAssociateRQPDU.h"
32 #include "gdcmAReleaseRPPDU.h"
33 #include "gdcmAReleaseRQPDU.h"
34 #include "gdcmPDataTFPDU.h"
35 #include "gdcmCompositeMessageFactory.h"
36 #include "gdcmNormalizedMessageFactory.h"
37 #include "gdcmBaseRootQuery.h"
38 #include "gdcmBasePDU.h"
39 
40 namespace gdcm
41 {
42 namespace network
43 {
44 
45 //eventually needs to be smartpointer'd
ConstructPDU(uint8_t itemtype)46 BasePDU* PDUFactory::ConstructPDU(uint8_t itemtype)
47 {
48   BasePDU* thePDU = nullptr;
49   switch (itemtype)
50     {
51   case 0x01:
52     thePDU = new AAssociateRQPDU;
53     break;
54   case 0x02:
55     thePDU = new AAssociateACPDU;
56     break;
57   case 0x03:
58     thePDU = new AAssociateRJPDU;
59     break;
60   case 0x04:
61     thePDU = new PDataTFPDU;
62     break;
63   case 0x05:
64     thePDU = new AReleaseRQPDU;
65     break;
66   case 0x06:
67     thePDU = new AReleaseRPPDU;
68     break;
69   case 0x07:
70     thePDU = new AAbortPDU;
71     break;
72     //default is that the PDU remains null
73     }
74   if( !thePDU )
75     {
76     gdcmErrorMacro( "Could not construct PDU for itemtype: " << (int)itemtype );
77     }
78   return thePDU;
79 }
80 
81 //determine which event was received by the PDU type
DetermineEventByPDU(const BasePDU * inPDU)82 EEventID PDUFactory::DetermineEventByPDU(const BasePDU* inPDU)
83 {
84   if(inPDU)
85     {
86     const AAssociateRQPDU* theAAssociateRQPDU = dynamic_cast<const AAssociateRQPDU*>(inPDU);
87     if (theAAssociateRQPDU != nullptr)
88       {
89       return eAASSOCIATE_RQPDUreceived;
90       }
91     const AAssociateACPDU* theAAssociateACPDU = dynamic_cast<const AAssociateACPDU*>(inPDU);
92     if (theAAssociateACPDU != nullptr)
93       {
94       return eASSOCIATE_ACPDUreceived;
95       }
96     const AAssociateRJPDU* theAAssociateRJPDU = dynamic_cast<const AAssociateRJPDU*>(inPDU);
97     if (theAAssociateRJPDU != nullptr)
98       {
99       return eASSOCIATE_RJPDUreceived;
100       }
101     const PDataTFPDU* thePDataTFPDU = dynamic_cast<const PDataTFPDU*>(inPDU);
102     if (thePDataTFPDU != nullptr)
103       {
104       ///
105       const PresentationDataValue &pdv = thePDataTFPDU->GetPresentationDataValue(0);
106       (void)pdv;
107 #if 0
108       int mh = pdv.GetMessageHeader();
109       if( mh == 3 )
110         {
111         // E.2 MESSAGE CONTROL HEADER ENCODING
112         // If bit 1 is set to 1, the following fragment shall contain the last
113         // fragment of a Message Data Set or of a Message Command.
114         std::cout << "This was the last fragment of the message data set" << std::endl;
115         }
116 #endif
117       return ePDATATFPDU;
118       }
119     const AReleaseRQPDU* theAReleaseRQPDU = dynamic_cast<const AReleaseRQPDU*>(inPDU);
120     if (theAReleaseRQPDU != nullptr)
121       {
122       return eARELEASE_RQPDUReceivedOpen;
123       }
124     const AReleaseRPPDU* theAReleaseRPPDU = dynamic_cast<const AReleaseRPPDU*>(inPDU);
125     if (theAReleaseRPPDU != nullptr)
126       {
127       return eARELEASE_RPPDUReceived;
128       }
129     const AAbortPDU* theAAbortPDU = dynamic_cast<const AAbortPDU*>(inPDU);
130     if (theAAbortPDU != nullptr)
131       {
132       return eAABORTPDUReceivedOpen;
133       }
134     }
135   return eEventDoesNotExist;
136 }
137 
ConstructReleasePDU()138 BasePDU* PDUFactory::ConstructReleasePDU()
139 {
140   AReleaseRQPDU* theAReleaseRQPDU = new AReleaseRQPDU();
141 
142   return theAReleaseRQPDU;
143 }
ConstructAbortPDU()144 BasePDU* PDUFactory::ConstructAbortPDU()
145 {
146   AAbortPDU* theAAbortPDU = new AAbortPDU();
147 
148   return theAAbortPDU;
149 }
CreateCEchoPDU(const ULConnection & inConnection)150 std::vector<BasePDU*> PDUFactory::CreateCEchoPDU(const ULConnection& inConnection)
151 {
152   std::vector<PresentationDataValue> pdv =
153     CompositeMessageFactory::ConstructCEchoRQ(inConnection);
154   std::vector<PresentationDataValue>::iterator pdvItor;
155   std::vector<BasePDU*> outVector;
156   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
157     {
158     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
159     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
160     outVector.push_back(thePDataTFPDU);
161     }
162   return outVector;
163 }
164 
CreateCMovePDU(const ULConnection & inConnection,const BaseRootQuery * inRootQuery)165 std::vector<BasePDU*> PDUFactory::CreateCMovePDU(const ULConnection&
166   inConnection, const BaseRootQuery* inRootQuery)
167 {
168   std::vector<PresentationDataValue> pdv =
169     CompositeMessageFactory::ConstructCMoveRQ(inConnection, inRootQuery );
170   std::vector<PresentationDataValue>::iterator pdvItor;
171   std::vector<BasePDU*> outVector;
172   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
173     {
174     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
175     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
176     outVector.push_back(thePDataTFPDU);
177     }
178   return outVector;
179 }
180 
CreateCStoreRQPDU(const ULConnection & inConnection,const File & file,bool writeDataSet)181 std::vector<BasePDU*> PDUFactory::CreateCStoreRQPDU(const ULConnection& inConnection,
182   const File& file, bool writeDataSet /*= true*/ )
183 {
184   std::vector<PresentationDataValue> pdv =
185     CompositeMessageFactory::ConstructCStoreRQ(inConnection, file, writeDataSet );
186   std::vector<PresentationDataValue>::iterator pdvItor;
187   std::vector<BasePDU*> outVector;
188   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
189     {
190     PDataTFPDU* thePDataTFPDU = new PDataTFPDU;
191     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
192     outVector.push_back(thePDataTFPDU);
193     }
194   return outVector;
195 }
196 
CreateCStoreRSPPDU(const DataSet * inDataSet,const BasePDU * inPDU)197 std::vector<BasePDU*> PDUFactory::CreateCStoreRSPPDU(const DataSet* inDataSet,
198   const BasePDU* inPDU)
199 {
200   std::vector<PresentationDataValue> pdv =
201     CompositeMessageFactory::ConstructCStoreRSP(inDataSet, inPDU );
202   std::vector<PresentationDataValue>::iterator pdvItor;
203   std::vector<BasePDU*> outVector;
204   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
205     {
206     PDataTFPDU* thePDataTFPDU = new PDataTFPDU;
207     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
208     outVector.push_back(thePDataTFPDU);
209     }
210   return outVector;
211 }
212 
CreateCFindPDU(const ULConnection & inConnection,const BaseRootQuery * inRootQuery)213 std::vector<BasePDU*> PDUFactory::CreateCFindPDU(const ULConnection& inConnection,
214   const BaseRootQuery* inRootQuery)
215 {
216 //still have to build this!
217   std::vector<PresentationDataValue> pdv =
218     CompositeMessageFactory::ConstructCFindRQ(inConnection, inRootQuery );
219   std::vector<PresentationDataValue>::iterator pdvItor;
220   std::vector<BasePDU*> outVector;
221   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
222     {
223     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
224     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
225     outVector.push_back(thePDataTFPDU);
226     }
227   return outVector;
228 
229 
230 }
231 
CreateNEventReportPDU(const ULConnection & inConnection,const BaseQuery * inQuery)232 std::vector<BasePDU*> PDUFactory::CreateNEventReportPDU		(const ULConnection& inConnection, const BaseQuery *inQuery)
233 {
234 //still have to build this!
235   std::vector<PresentationDataValue> pdv =
236 	  NormalizedMessageFactory::ConstructNEventReport(inConnection, inQuery );
237   std::vector<PresentationDataValue>::iterator pdvItor;
238   std::vector<BasePDU*> outVector;
239   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
240     {
241     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
242     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
243     outVector.push_back(thePDataTFPDU);
244     }
245   return outVector;
246 
247 
248 }
CreateNGetPDU(const ULConnection & inConnection,const BaseQuery * inQuery)249 std::vector<BasePDU*> PDUFactory::CreateNGetPDU				(const ULConnection& inConnection, const BaseQuery *inQuery)
250 {
251 //still have to build this!
252   std::vector<PresentationDataValue> pdv =
253     NormalizedMessageFactory::ConstructNGet(inConnection, inQuery );
254   std::vector<PresentationDataValue>::iterator pdvItor;
255   std::vector<BasePDU*> outVector;
256   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
257     {
258     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
259     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
260     outVector.push_back(thePDataTFPDU);
261     }
262   return outVector;
263 
264 
265 }
CreateNSetPDU(const ULConnection & inConnection,const BaseQuery * inQuery)266 std::vector<BasePDU*> PDUFactory::CreateNSetPDU				(const ULConnection& inConnection, const BaseQuery *inQuery)
267 {
268 //still have to build this!
269   std::vector<PresentationDataValue> pdv =
270     NormalizedMessageFactory::ConstructNSet(inConnection, inQuery );
271   std::vector<PresentationDataValue>::iterator pdvItor;
272   std::vector<BasePDU*> outVector;
273   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
274     {
275     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
276     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
277     outVector.push_back(thePDataTFPDU);
278     }
279   return outVector;
280 
281 
282 }
CreateNActionPDU(const ULConnection & inConnection,const BaseQuery * inQuery)283 std::vector<BasePDU*> PDUFactory::CreateNActionPDU			(const ULConnection& inConnection, const BaseQuery *inQuery)
284 {
285 //still have to build this!
286   std::vector<PresentationDataValue> pdv =
287     NormalizedMessageFactory::ConstructNAction(inConnection, inQuery );
288   std::vector<PresentationDataValue>::iterator pdvItor;
289   std::vector<BasePDU*> outVector;
290   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
291     {
292     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
293     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
294     outVector.push_back(thePDataTFPDU);
295     }
296   return outVector;
297 
298 
299 }
CreateNCreatePDU(const ULConnection & inConnection,const BaseQuery * inQuery)300 std::vector<BasePDU*> PDUFactory::CreateNCreatePDU			(const ULConnection& inConnection, const BaseQuery *inQuery)
301 {
302 //still have to build this!
303   std::vector<PresentationDataValue> pdv =
304 	  NormalizedMessageFactory::ConstructNCreate(inConnection, inQuery );
305   std::vector<PresentationDataValue>::iterator pdvItor;
306   std::vector<BasePDU*> outVector;
307   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
308     {
309     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
310     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
311     outVector.push_back(thePDataTFPDU);
312     }
313   return outVector;
314 
315 
316 }
CreateNDeletePDU(const ULConnection & inConnection,const BaseQuery * inQuery)317 std::vector<BasePDU*> PDUFactory::CreateNDeletePDU			(const ULConnection& inConnection, const BaseQuery *inQuery)
318 {
319 //still have to build this!
320   std::vector<PresentationDataValue> pdv =
321     NormalizedMessageFactory::ConstructNDelete(inConnection, inQuery );
322   std::vector<PresentationDataValue>::iterator pdvItor;
323   std::vector<BasePDU*> outVector;
324   for (pdvItor = pdv.begin(); pdvItor < pdv.end(); pdvItor++)
325     {
326     PDataTFPDU* thePDataTFPDU = new PDataTFPDU();
327     thePDataTFPDU->AddPresentationDataValue( *pdvItor );
328     outVector.push_back(thePDataTFPDU);
329     }
330   return outVector;
331 
332 
333 }
334 
335 
336 //given data pdus, produce the presentation data values stored within.
337 //all operations have these as the payload of the data sending operation
338 //however, echo does not have a dataset in the pdv.
GetPDVs(const std::vector<BasePDU * > & inDataPDUs)339 std::vector<PresentationDataValue> PDUFactory::GetPDVs(const std::vector<BasePDU*> & inDataPDUs)
340 {
341   std::vector<BasePDU*>::const_iterator itor;
342   std::vector<PresentationDataValue> outPDVs;
343   for (itor = inDataPDUs.begin(); itor < inDataPDUs.end(); itor++)
344     {
345     PDataTFPDU* thePDataTFPDU = dynamic_cast<PDataTFPDU*>(*itor);
346     if (thePDataTFPDU == nullptr)
347       {
348       assert(0); //shouldn't really get here.
349       return outPDVs; //just stop now, no longer with data pdus.
350       }
351     size_t theNumPDVsinPDU = thePDataTFPDU->GetNumberOfPresentationDataValues();
352     for (size_t i = 0; i < theNumPDVsinPDU; i++)
353       {
354       outPDVs.push_back(thePDataTFPDU->GetPresentationDataValue(i));
355       }
356     }
357   return outPDVs;
358 }
359 } // end namespace network
360 } // end namespace gdcm
361