PageRenderTime 33ms CodeModel.GetById 2ms app.highlight 23ms RepoModel.GetById 2ms app.codeStats 0ms

/package/app/app/generator/CSharpClientGenerator.php

https://bitbucket.org/pandaos/kaltura
PHP | 906 lines | 780 code | 98 blank | 28 comment | 113 complexity | 274a66aca9a13c32cda98fd2830172d0 MD5 | raw file
  1<?php
  2class CSharpClientGenerator extends ClientGeneratorFromXml
  3{
  4	private $_doc = null;
  5	private $_csprojIncludes = array();
  6	private $_classInheritance = array();
  7	private $_enums = array();
  8	
  9	function CSharpClientGenerator($xmlPath)
 10	{
 11		parent::ClientGeneratorFromXml($xmlPath, realpath("sources/csharp"));
 12		$this->_doc = new DOMDocument();
 13		$this->_doc->load($this->_xmlFile);
 14	}
 15	
 16	function generate() 
 17	{
 18		parent::generate();
 19		
 20		$this->removeFilesFromSource();
 21		
 22		$xpath = new DOMXPath($this->_doc);
 23		$this->loadClassInheritance($xpath->query("/xml/classes/class"));
 24		$this->loadEnums($xpath->query("/xml/enums/enum"));
 25		
 26		// enumes $ types
 27		$enumNodes = $xpath->query("/xml/enums/enum");
 28		foreach($enumNodes as $enumNode)
 29		{
 30			$this->writeEnum($enumNode);
 31		}
 32		
 33		$classNodes = $xpath->query("/xml/classes/class");
 34		foreach($classNodes as $classNode)
 35		{
 36			$this->writeClass($classNode);
 37		}
 38		
 39		$this->writeObjectFactoryClass($classNodes);
 40		
 41		$serviceNodes = $xpath->query("/xml/services/service");
 42		
 43		$this->startNewTextBlock();
 44		foreach($serviceNodes as $serviceNode)
 45		{
 46			$this->writeService($serviceNode);
 47		}
 48		
 49		$this->writeMainClient($serviceNodes);
 50		
 51		$this->writeCsproj();
 52	}
 53	
 54	function writeEnum(DOMElement $enumNode)
 55	{
 56		$enumName = $enumNode->getAttribute("name");
 57		$s = "";
 58		$s .= "namespace Kaltura"."\n";
 59		$s .= "{"."\n";
 60		
 61		if ($enumNode->getAttribute("enumType") == "string")
 62		{
 63			$s .= "	public sealed class $enumName : KalturaStringEnum"."\n";
 64			$s .= "	{"."\n";
 65			
 66			foreach($enumNode->childNodes as $constNode)
 67			{
 68				if ($constNode->nodeType != XML_ELEMENT_NODE)
 69					continue;
 70					
 71				$propertyName = $constNode->getAttribute("name");
 72				$propertyValue = $constNode->getAttribute("value");
 73				$s .= "		public static readonly $enumName $propertyName = new $enumName(\"$propertyValue\");"."\n";
 74			}
 75			$s .= "\n";
 76			$s .= "		private $enumName(string name) : base(name) { }"."\n";
 77			$s .= "	}"."\n";
 78			$s .= "}"."\n";
 79		}
 80		else
 81		{
 82			$s .= "	public enum $enumName"."\n";
 83			$s .= "	{"."\n";
 84			
 85			foreach($enumNode->childNodes as $constNode)
 86			{
 87				if ($constNode->nodeType != XML_ELEMENT_NODE)
 88					continue;
 89					
 90				$propertyName = $constNode->getAttribute("name");
 91				$propertyValue = $constNode->getAttribute("value");
 92				$s .= "		$propertyName = $propertyValue,"."\n";
 93			}
 94			$s .= "	}"."\n";
 95			$s .= "}"."\n";
 96		}
 97		$file = "Enums/$enumName.cs";
 98		$this->addFile("KalturaClient/".$file, $s);
 99		$this->_csprojIncludes[] = $file; 
100	}
101	
102	function writeClass(DOMElement $classNode)
103	{
104		$this->startNewTextBlock();
105		$this->appendLine("using System;");
106		$this->appendLine("using System.Xml;");
107		$this->appendLine("using System.Collections.Generic;");
108		$this->appendLine();
109		$this->appendLine("namespace Kaltura");
110		$this->appendLine("{");
111		$type = $classNode->getAttribute("name");
112		// class definition
113		if ($classNode->hasAttribute("base"))
114		{
115			$this->appendLine("	public class $type : ".$classNode->getAttribute("base"));
116		}
117		else
118		{
119			$this->appendLine("	public class $type : KalturaObjectBase");
120		}
121		$this->appendLine("	{");
122		
123		// we want to make the orderBy property strongly typed with the corresponding string enum
124		$isFilter = false;
125		if ($this->isClassInherit($type, "KalturaFilter")) 
126		{
127			$orderByType = str_replace("Filter", "OrderBy", $type);
128			if ($this->enumExists($orderByType)) 
129			{
130				$orderByElement = $classNode->ownerDocument->createElement("property");
131				$orderByElement->setAttribute("name", "orderBy");
132				$orderByElement->setAttribute("type", "string");
133				$orderByElement->setAttribute("enumType", $orderByType);
134				$classNode->appendChild($orderByElement);
135				$isFilter = true;
136			}
137		}
138
139		$properties = array();
140		foreach($classNode->childNodes as $propertyNode)
141		{
142			if ($propertyNode->nodeType != XML_ELEMENT_NODE)
143				continue;
144			
145			$property = array(
146				"name" => null,
147				"type" => null,
148				"default" => null,
149				"isNew" => false
150			);
151			
152			$propType = $propertyNode->getAttribute("type");
153			$propName = $propertyNode->getAttribute("name");
154			$isEnum = $propertyNode->hasAttribute("enumType");
155			$dotNetPropName = $this->upperCaseFirstLetter($propName);
156			$property["name"] = $dotNetPropName;
157			
158			if ($isEnum)
159				$dotNetPropType = $propertyNode->getAttribute("enumType");
160			else if ($propType == "array")
161				$dotNetPropType = "IList<".$propertyNode->getAttribute("arrayType").">";
162			else if ($propType == "bool")
163				$dotNetPropType  = "bool?";
164			else
165				$dotNetPropType = $propType;
166				
167			$property["type"] = $dotNetPropType;
168			if ($isFilter && $dotNetPropName == "OrderBy")
169				$property["isNew"] = true;
170				
171			switch($propType)
172			{
173				case "int":
174					if ($isEnum)
175						$property["default"] = "($dotNetPropType)Int32.MinValue";
176					else
177						$property["default"] = "Int32.MinValue";
178					break;
179				case "string":
180					$property["default"] = "null";
181					break;
182				case "bool":
183					$property["default"] = "false";
184					break;
185				case "float":
186					$property["default"] = "Single.MinValue";
187					break;
188			}
189			
190			$properties[] = $property;
191		}
192		// private fields
193		$this->appendLine("		#region Private Fields");
194		foreach($properties as $property)
195		{
196			$propertyLine = "private";
197			
198			$propertyLine .= " {$property['type']} _{$property['name']}";
199			
200			if (!is_null($property["default"]))
201				$propertyLine .= " = {$property['default']}";
202				
203			$propertyLine .= ";";
204			
205			$this->appendLine("		" . $propertyLine);
206		}
207		$this->appendLine("		#endregion");
208		
209		$this->appendLine();
210		
211		// properties 
212		$this->appendLine("		#region Properties");
213		foreach($properties as $property)
214		{
215			$propertyLine = "public";
216			if ($property['isNew'])
217				$propertyLine .= " new";
218			
219			$propertyLine .= " {$property['type']} {$property['name']}";
220			
221			$this->appendLine("		" . $propertyLine);
222			$this->appendLine("		{");
223			$this->appendLine("			get { return _{$property['name']}; }");
224			$this->appendLine("			set ");
225			$this->appendLine("			{ ");
226			$this->appendLine("				_{$property['name']} = value;");
227			$this->appendLine("				OnPropertyChanged(\"{$property['name']}\");");
228			$this->appendLine("			}");
229			$this->appendLine("		}");
230		}
231		$this->appendLine("		#endregion");
232		$this->appendLine();
233		
234		$this->appendLine("		#region CTor");
235		// CTor
236		$this->appendLine("		public $type()");
237		$this->appendLine("		{");
238		$this->appendLine("		}");
239		$this->appendLine("");
240		
241		// CTor For XmlElement
242		if ($classNode->hasAttribute("base"))
243		{
244			$this->appendLine("		public $type(XmlElement node) : base(node)");
245		}
246		else
247		{
248			$this->appendLine("		public $type(XmlElement node)");
249		}
250		
251		$this->appendLine("		{");
252		if ($classNode->childNodes->length)
253		{
254			$this->appendLine("			foreach (XmlElement propertyNode in node.ChildNodes)"); 
255			$this->appendLine("			{");
256			$this->appendLine("				string txt = propertyNode.InnerText;");
257			$this->appendLine("				switch (propertyNode.Name)");
258			$this->appendLine("				{");
259			foreach($classNode->childNodes as $propertyNode)
260			{
261				if ($propertyNode->nodeType != XML_ELEMENT_NODE)
262					continue;
263					
264				$propType = $propertyNode->getAttribute("type");
265				$propName = $propertyNode->getAttribute("name");
266				$isEnum = $propertyNode->hasAttribute("enumType");
267				$dotNetPropName = $this->upperCaseFirstLetter($propName);
268				$this->appendLine("					case \"$propName\":");
269				switch($propType)
270				{
271					case "int":
272						if ($isEnum)
273						{
274							$enumType = $propertyNode->getAttribute("enumType");
275							$this->appendLine("						this.$dotNetPropName = ($enumType)ParseEnum(typeof($enumType), txt);");
276						}
277						else
278							$this->appendLine("						this.$dotNetPropName = ParseInt(txt);");
279						break;
280					case "string":
281						if ($isEnum)
282						{
283							$enumType = $propertyNode->getAttribute("enumType");
284							$this->appendLine("						this.$dotNetPropName = ($enumType)KalturaStringEnum.Parse(typeof($enumType), txt);");
285						}
286						else
287							$this->appendLine("						this.$dotNetPropName = txt;");
288						break;
289					case "bool":
290						$this->appendLine("						this.$dotNetPropName = ParseBool(txt);");
291						break;
292					case "float":
293						$this->appendLine("						this.$dotNetPropName = ParseFloat(txt);");
294						break;
295					case "array":
296						$arrayType = $propertyNode->getAttribute("arrayType");
297						$this->appendLine("						this.$dotNetPropName = new List<$arrayType>();");
298						$this->appendLine("						foreach(XmlElement arrayNode in propertyNode.ChildNodes)");
299						$this->appendLine("						{");
300						$this->appendLine("							this.$dotNetPropName.Add(($arrayType)KalturaObjectFactory.Create(arrayNode));");
301						$this->appendLine("						}");
302						break;
303					default: // sub object
304						$this->appendLine("						this.$dotNetPropName = ($propType)KalturaObjectFactory.Create(propertyNode);");
305						break;
306				}
307				$this->appendLine("						continue;");
308			}
309			$this->appendLine("				}");
310			$this->appendLine("			}");
311		}
312		$this->appendLine("		}");
313		$this->appendLine("		#endregion");
314		$this->appendLine("");
315		
316		$this->appendLine("		#region Methods");
317		// ToParams method
318		$this->appendLine("		public override KalturaParams ToParams()");
319		$this->appendLine("		{");
320		$this->appendLine("			KalturaParams kparams = base.ToParams();");
321		foreach($classNode->childNodes as $propertyNode)
322		{
323			if ($propertyNode->nodeType != XML_ELEMENT_NODE)
324				continue;
325				
326			$propType = $propertyNode->getAttribute("type");
327			$propName = $propertyNode->getAttribute("name");
328			$isEnum = $propertyNode->hasAttribute("enumType");
329			$dotNetPropName = $this->upperCaseFirstLetter($propName);
330			
331			switch($propType)
332			{
333				case "int":
334					if ($isEnum)
335						$this->appendLine("			kparams.AddEnumIfNotNull(\"$propName\", this.$dotNetPropName);");
336					else
337						$this->appendLine("			kparams.AddIntIfNotNull(\"$propName\", this.$dotNetPropName);");
338					break;
339				case "string":
340					if ($isEnum)
341						$this->appendLine("			kparams.AddStringEnumIfNotNull(\"$propName\", this.$dotNetPropName);");
342					else
343						$this->appendLine("			kparams.AddStringIfNotNull(\"$propName\", this.$dotNetPropName);");
344					break;
345				case "bool":
346					$this->appendLine("			kparams.AddBoolIfNotNull(\"$propName\", this.$dotNetPropName);");
347					break;
348				case "float":
349					$this->appendLine("			kparams.AddFloatIfNotNull(\"$propName\", this.$dotNetPropName);");
350					break;
351				case "enum":
352					$this->appendLine("			kparams.AddEnumIfNotNull(\"$propName\", this.$dotNetPropName);");
353					break;
354				case "array":
355					$arrayType = $propertyNode->getAttribute("arrayType");
356					$this->appendLine("			if (this.$dotNetPropName != null)");
357					$this->appendLine("			{");
358					$this->appendLine("				if (this.$dotNetPropName.Count == 0)");
359					$this->appendLine("				{");
360					$this->appendLine("					kparams.Add(\"".$propName.":-\", \"\");");
361					$this->appendLine("				}");
362					$this->appendLine("				else");
363					$this->appendLine("				{");
364					$this->appendLine("					int i = 0;");
365					$this->appendLine("					foreach ($arrayType item in this.$dotNetPropName)");
366					$this->appendLine("					{");
367					$this->appendLine("						kparams.Add(\"".$propName.":\" + i + \":objectType\", item.GetType().Name);");
368					$this->appendLine("						kparams.Add(\"".$propName.":\" + i, item.ToParams());");
369					$this->appendLine("						i++;");
370					$this->appendLine("					}");
371					$this->appendLine("				}");
372					$this->appendLine("			}");
373					break;
374				default: // for objects
375					$this->appendLine("			if (this.$dotNetPropName != null)");
376					$this->appendLine("				kparams.Add(\"$propName\", this.$dotNetPropName.ToParams());");
377					break;
378			}
379		}
380		$this->appendLine("			return kparams;");
381		$this->appendLine("		}");
382		$this->appendLine("		#endregion");
383		
384		// close class
385		$this->appendLine("	}");
386		$this->appendLine("}");
387		$this->appendLine();
388		
389		$file = "Types/$type.cs";
390		$this->addFile("KalturaClient/".$file, $this->getTextBlock());
391		$this->_csprojIncludes[] = $file; 
392	}
393	
394	function writeObjectFactoryClass(DOMNodeList $classNodes)
395	{
396		$this->startNewTextBlock();
397		$this->appendLine("using System;");
398		$this->appendLine("using System.Text;");
399		$this->appendLine("using System.Xml;");
400		$this->appendLine("using System.Runtime.Serialization;");
401		$this->appendLine();
402		$this->appendLine("namespace Kaltura");
403		$this->appendLine("{");
404		$this->appendLine("	public static class KalturaObjectFactory");
405		$this->appendLine("	{");
406		$this->appendLine("		public static object Create(XmlElement xmlElement)");
407		$this->appendLine("		{");
408		$this->appendLine("			if (xmlElement[\"objectType\"] == null)");
409		$this->appendLine("			{");
410		$this->appendLine("				return null;");
411		$this->appendLine("			}");
412		$this->appendLine("			switch (xmlElement[\"objectType\"].InnerText)");
413		$this->appendLine("			{");
414		foreach($classNodes as $classNode)
415		{
416			$this->appendLine("				case \"".$classNode->getAttribute("name")."\":");
417			$this->appendLine("					return new ".$classNode->getAttribute("name")."(xmlElement);");	
418		}
419		$this->appendLine("			}");
420		$this->appendLine("			throw new SerializationException(\"Invalid object type\");");
421		$this->appendLine("		}");
422		$this->appendLine("	}");
423		$this->appendLine("}");
424		
425		$file = "KalturaObjectFactory.cs";
426		$this->addFile("KalturaClient/".$file, $this->getTextBlock());
427		$this->_csprojIncludes[] = $file;
428	}
429	
430	function writeCsproj()
431	{
432		$csprojDoc = new DOMDocument();
433		$csprojDoc->formatOutput = true;
434		$csprojDoc->load($this->_sourcePath."/KalturaClient/KalturaClient.csproj");
435		$csprojXPath = new DOMXPath($csprojDoc);
436		$csprojXPath->registerNamespace("m", "http://schemas.microsoft.com/developer/msbuild/2003");
437		$compileNodes = $csprojXPath->query("//m:ItemGroup/m:Compile/..");
438		$compileItemGroupElement = $compileNodes->item(0); 
439		
440		foreach($this->_csprojIncludes as $include)
441		{
442			$compileElement = $csprojDoc->createElement("Compile");
443			$compileElement->setAttribute("Include", str_replace("/","\\", $include));
444			$compileItemGroupElement->appendChild($compileElement);
445		}
446		$this->addFile("KalturaClient/KalturaClient.csproj", $csprojDoc->saveXML());
447	}
448	
449	function writeService(DOMElement $serviceNode)
450	{
451		$this->startNewTextBlock();
452		$this->appendLine("using System;");
453		$this->appendLine("using System.Xml;");
454		$this->appendLine("using System.Collections.Generic;");
455		$this->appendLine("using System.IO;");
456		$this->appendLine();
457		$this->appendLine("namespace Kaltura");
458		$this->appendLine("{");
459		$serviceName = $serviceNode->getAttribute("name");
460		$serviceId = $serviceNode->getAttribute("id");
461
462		
463		$dotNetServiceName = $this->upperCaseFirstLetter($serviceName)."Service";
464		$dotNetServiceType = "Kaltura" . $dotNetServiceName;
465		
466		$this->appendLine();
467		$this->appendLine("	public class $dotNetServiceType : KalturaServiceBase");
468		$this->appendLine("	{");
469		$this->appendLine("	public $dotNetServiceType(KalturaClient client)");
470		$this->appendLine("			: base(client)");
471		$this->appendLine("		{");
472		$this->appendLine("		}");	   
473		 
474		
475		$actionNodes = $serviceNode->childNodes;
476		foreach($actionNodes as $actionNode)
477		{
478			if ($actionNode->nodeType != XML_ELEMENT_NODE)
479				continue;
480				
481			$this->writeAction($serviceId, $actionNode);
482		}
483		$this->appendLine("	}");
484		$this->appendLine("}");
485		
486		$file = "Services/".$dotNetServiceName.".cs";
487		$this->addFile("KalturaClient/".$file, $this->getTextBlock());
488		$this->_csprojIncludes[] = $file; 
489	}
490	
491	function writeAction($serviceId, DOMElement $actionNode)
492	{
493		$action = $actionNode->getAttribute("name");
494		$resultNode = $actionNode->getElementsByTagName("result")->item(0);
495		$resultType = $resultNode->getAttribute("type");
496	    
497	    if($resultType == 'file')
498	    	return;
499		
500		switch($resultType)
501		{
502			case null:
503				$dotNetOutputType = "void";
504				break;
505			case "array":
506				$arrayType = $resultNode->getAttribute("arrayType"); 
507				$dotNetOutputType = "IList<".$arrayType.">";
508				break;
509			default:
510				$dotNetOutputType = $resultType;
511				break;
512		}
513			
514		$signaturePrefix = "public $dotNetOutputType ".$this->upperCaseFirstLetter($action)."(";
515			
516		$paramNodes = $actionNode->getElementsByTagName("param");
517		
518		// check for needed overloads
519		$mandatoryParams = array();
520		$optionalParams = array();
521		foreach($paramNodes as $paramNode)
522		{
523			$optional = $paramNode->getAttribute("optional");
524			if ($optional == "1")
525				$optionalParams[] = $paramNode;
526			else
527				$mandatoryParams[] = $paramNode;
528		}
529		
530		for($overloadNumber = 0; $overloadNumber < count($optionalParams); $overloadNumber++)
531		{
532			$currentOptionalParams = array_slice($optionalParams, 0, $overloadNumber);
533			$defaultParams = array_slice(array_merge($mandatoryParams, $optionalParams), 0, count($mandatoryParams) + $overloadNumber + 1);
534			$signature = $this->getSignature(array_merge($mandatoryParams, $currentOptionalParams));
535			
536			// write the overload
537			$this->appendLine();	
538			$this->appendLine("		$signaturePrefix$signature");
539			$this->appendLine("		{");
540			$paramsStr = "";
541			foreach($defaultParams as $paramNode)
542			{
543				$optional = $paramNode->getAttribute("optional");
544				if ($optional == "1" && ! in_array ( $paramNode, $currentOptionalParams, true ))
545				{
546					$type = $paramNode->getAttribute("type");
547					if ($type == "string")
548					{
549						$value = $paramNode->getAttribute("default");
550						if($value == 'null')
551							$paramsStr .=  "null";
552						else
553							$paramsStr .=  "\"".$paramNode->getAttribute("default")."\"";
554					}
555					else if ($type == "int" && $paramNode->hasAttribute("enumType"))
556					{
557						$value = $paramNode->getAttribute("default");
558						if ($value == "null")
559							$value = "Int32.MinValue";
560						$paramsStr .=  "(".$paramNode->getAttribute("enumType").")(".$value.")";
561					}
562					elseif ($type == "int" && $paramNode->getAttribute("default") == "null") // because Partner.GetUsage has an int field with empty default value
563						$paramsStr .= "Int32.MinValue";
564					else
565						$paramsStr .=  $paramNode->getAttribute("default");
566				}
567				else
568				{
569					$paramName = $paramNode->getAttribute("name");
570					$paramsStr .=  $this->fixParamName($paramName);
571				}
572				
573				$paramsStr .= ", ";
574			}
575			
576			if ($this->endsWith($paramsStr, ", "))
577				$paramsStr = substr($paramsStr, 0, strlen($paramsStr) - 2);
578				
579			if($resultType)
580				$this->appendLine("			return this.".$this->upperCaseFirstLetter($action)."($paramsStr);");
581			else
582				$this->appendLine("			this.".$this->upperCaseFirstLetter($action)."($paramsStr);");
583				
584			$this->appendLine("		}");
585		}
586		
587		$signature = $this->getSignature(array_merge($mandatoryParams, $optionalParams));
588		
589		$this->appendLine();	
590		$this->appendLine("		$signaturePrefix$signature");
591		$this->appendLine("		{");
592		
593		$this->appendLine("			KalturaParams kparams = new KalturaParams();");
594		$haveFiles = false;
595		foreach($paramNodes as $paramNode)
596		{
597			$paramType = $paramNode->getAttribute("type");
598			$paramName = $paramNode->getAttribute("name");
599			$isEnum = $paramNode->hasAttribute("enumType");
600			
601			if ($haveFiles === false && $paramType === "file")
602			{
603				$haveFiles = true;
604				$this->appendLine("			KalturaFiles kfiles = new KalturaFiles();");
605			}	 
606
607			switch ($paramType)
608			{
609				case "string":
610					if ($isEnum)
611						$this->appendLine("			kparams.AddStringEnumIfNotNull(\"$paramName\", ".$this->fixParamName($paramName).");");
612					else
613						$this->appendLine("			kparams.AddStringIfNotNull(\"$paramName\", ".$this->fixParamName($paramName).");");
614					break;
615				case "float":
616						$this->appendLine("			kparams.AddFloatIfNotNull(\"$paramName\", ".$this->fixParamName($paramName).");");
617					break;
618			   	case "int":
619					if ($isEnum)
620						$this->appendLine("			kparams.AddEnumIfNotNull(\"$paramName\", ".$this->fixParamName($paramName).");");
621					else
622						$this->appendLine("			kparams.AddIntIfNotNull(\"$paramName\", ".$this->fixParamName($paramName).");");
623					break;
624				case "bool":
625					$this->appendLine("			kparams.AddBoolIfNotNull(\"$paramName\", ".$this->fixParamName($paramName).");");
626					break;
627				case "array":
628					$this->appendLine("			foreach(".$paramNode->getAttribute("arrayType")." obj in ".$this->fixParamName($paramName).")");
629					$this->appendLine("			{");
630					$this->appendLine("				kparams.Add(\"$paramName\", obj.ToParams());");
631					$this->appendLine("			}");
632					break;
633				case "file":
634					$this->appendLine("			kfiles.Add(\"$paramName\", ".$this->fixParamName($paramName).");");
635					break;
636				default: // for objects
637					$this->appendLine("			if (".$this->fixParamName($paramName)." != null)");
638					$this->appendLine("				kparams.Add(\"$paramName\", ".$this->fixParamName($paramName).".ToParams());");
639					break;
640			}
641		}
642		
643		if ($haveFiles)
644			$this->appendLine("			_Client.QueueServiceCall(\"$serviceId\", \"$action\", kparams, kfiles);");
645		else
646			$this->appendLine("			_Client.QueueServiceCall(\"$serviceId\", \"$action\", kparams);");
647		
648		$this->appendLine("			if (this._Client.IsMultiRequest)");
649		if (!$resultType) 
650			$this->appendLine("				return;");
651		else if ($resultType == "int" || $resultNode == "float")
652			$this->appendLine("				return 0;");
653		else if ($resultType == "bool")
654			$this->appendLine("				return false;");
655		else
656			$this->appendLine("				return null;");
657
658		$this->appendLine("			XmlElement result = _Client.DoQueue();"); 
659		
660		if ($resultType)
661		{
662			switch ($resultType)
663			{
664				case "array":
665					$arrayType = $resultNode->getAttribute("arrayType");
666					$this->appendLine("			IList<$arrayType> list = new List<$arrayType>();");
667					$this->appendLine("			foreach(XmlElement node in result.ChildNodes)");
668					$this->appendLine("			{");
669					$this->appendLine("				list.Add(($arrayType)KalturaObjectFactory.Create(node));");
670					$this->appendLine("			}");
671					$this->appendLine("			return list;");
672					break;
673				case "int":
674					$this->appendLine("			return int.Parse(result.InnerText);");
675					break;
676				case "float":
677					$this->appendLine("			return Single.Parse(result.InnerText);");
678					break;
679				case "bool":
680					$this->appendLine("			if (result.InnerText == \"1\")");
681					$this->appendLine("				return true;");
682					$this->appendLine("			return false;");
683					break;
684				case "string":
685					$this->appendLine("			return result.InnerText;");
686					break;
687				default:
688					$this->appendLine("			return ($resultType)KalturaObjectFactory.Create(result);");
689					break;
690			}
691		}
692		$this->appendLine("		}");
693	}
694	
695	function getSignature($paramNodes)
696	{
697		$signature = "";
698		foreach($paramNodes as $paramNode)
699		{
700			$paramType = $paramNode->getAttribute("type");
701			$paramName = $paramNode->getAttribute("name");
702			$isEnum = $paramNode->hasAttribute("enumType");
703			
704			switch($paramType)
705			{
706				case "array":
707					$dotNetType = "IList<".$paramNode->getAttribute("arrayType").">";
708					break;
709				case "file":
710					$dotNetType = "FileStream";
711					break;
712				case "int":
713					if ($isEnum)
714						$dotNetType = $paramNode->getAttribute("enumType");
715					else 
716						$dotNetType = $paramType;			
717					break;			
718				default:
719					if ($isEnum)
720						$dotNetType = $paramNode->getAttribute("enumType");
721					else 
722						$dotNetType = $paramType;		 
723					break;
724			}
725
726			$signature .= "$dotNetType ".$this->fixParamName($paramName).", ";
727		}
728		if ($this->endsWith($signature, ", "))
729			$signature = substr($signature, 0, strlen($signature) - 2);
730		$signature .= ")";
731		
732		return $signature;
733	}
734	
735	function writeMainClient(DOMNodeList  $serviceNodes)
736	{
737		$apiVersion = $this->_doc->documentElement->getAttribute('apiVersion');
738	
739		$this->startNewTextBlock();
740		
741		$this->appendLine("using System;");
742		$this->appendLine();
743		
744		$this->appendLine("namespace Kaltura");
745		$this->appendLine("{");
746		$this->appendLine("	public class KalturaClient : KalturaClientBase");
747		$this->appendLine("	{");
748		$this->appendLine("		public KalturaClient(KalturaConfiguration config)");
749		$this->appendLine("			: base(config)");
750		$this->appendLine("		{");
751		$this->appendLine("				_ApiVersion = \"$apiVersion\";");
752		$this->appendLine("		}");
753		foreach($serviceNodes as $serviceNode)
754		{
755			$serviceName = $serviceNode->getAttribute("name");
756			$dotNetServiceName = $this->upperCaseFirstLetter($serviceName)."Service";
757			$dotNetServiceType = "Kaltura" . $dotNetServiceName;
758			
759			$this->appendLine();		
760			$this->appendLine("		$dotNetServiceType _$dotNetServiceName;");
761			$this->appendLine("		public $dotNetServiceType $dotNetServiceName");
762			$this->appendLine("		{");
763			$this->appendLine("			get");
764			$this->appendLine("			{");
765			$this->appendLine("				if (_$dotNetServiceName == null)");
766			$this->appendLine("					_$dotNetServiceName = new $dotNetServiceType(this);");
767			$this->appendLine("");
768			$this->appendLine("				return _$dotNetServiceName;");
769			$this->appendLine("			}");
770			$this->appendLine("		}");
771		}
772		$this->appendLine("	}");
773		$this->appendLine("}");
774		
775		$this->addFile("KalturaClient/KalturaClient.cs", $this->getTextBlock());
776
777		// not needed because it is included in the sources
778		//$this->_csprojIncludes[] = "KalturaClient.cs";
779	}
780	
781	private function loadEnums(DOMNodeList $enums)
782	{
783		foreach($enums as $item)
784		{
785			$this->_enums[$item->getAttribute("name")] = null;
786		}
787	}
788	
789	private function loadClassInheritance(DOMNodeList $classes)
790	{
791		// first fill the base classes
792		foreach($classes as $item)
793		{
794			$class = $item->getAttribute("name");
795			if (!$item->hasAttribute("base"))
796			{
797				$this->_classInheritance[$class] = array();
798			}
799		}
800		
801		// now fill recursively the childs
802		foreach($this->_classInheritance as $class => $null)
803		{
804			$this->loadChildsForInheritance($classes, $class, $this->_classInheritance);
805		}
806	}
807	
808	private function loadChildsForInheritance(DOMNodeList $classes, $baseClass, array &$baseClassChilds)
809	{
810		$baseClassChilds[$baseClass] = $this->getChildsForParentClass($classes, $baseClass);
811		
812		foreach($baseClassChilds[$baseClass] as $childClass => $null)
813		{
814			$this->loadChildsForInheritance($classes, $childClass, $baseClassChilds[$baseClass]);
815		}
816	}
817	
818	private function getChildsForParentClass(DOMNodeList $classes, $parentClass)
819	{
820		$childs = array();
821		foreach($classes as $item2)
822		{
823			$currentParentClass = $item2->getAttribute("base");
824			$class = $item2->getAttribute("name");
825			if ($currentParentClass === $parentClass) 
826			{
827				$childs[$class] = array();
828			}
829		}
830		return $childs;
831	}
832	
833	private function isClassInherit($class, $baseClass)
834	{
835		$classTree = $this->getClassChildsTree($this->_classInheritance, $baseClass);
836		if (is_null($classTree))
837			return false;
838		else 
839		{
840			if (is_null($this->getClassChildsTree($classTree, $class)))
841				return false;
842			else
843				return true;
844		}
845	}
846	
847	/**
848	 * Finds the class in the multidimensional array and returns a multidimensional array with its child classes
849	 * Null if not found
850	 * 
851	 * @param array $classes
852	 * @param string $class
853	 */
854	private function getClassChildsTree(array $classes, $class)
855	{
856		foreach($classes as $tempClass => $null)
857		{
858			if ($class === $tempClass)
859			{
860				return $classes[$class];
861			}
862			else 
863			{
864				$subArray = $this->getClassChildsTree($classes[$tempClass], $class);
865				if (!is_null($subArray))
866					return $subArray;
867			}
868		}
869		return null;
870	}
871	
872	private function enumExists($enum)
873	{
874		return array_key_exists($enum, $this->_enums);
875	}
876	
877	private function removeFilesFromSource()
878	{
879		$files = array_keys($this->_files);
880		foreach($files as $file)
881		{
882			if ($file == "KalturaClient.suo")
883				unset($this->_files["KalturaClient.suo"]);
884			$dirname = pathinfo($file, PATHINFO_DIRNAME);
885			if ($this->endsWith($dirname, "Debug"))
886				unset($this->_files[$file]);
887			if ($this->endsWith($dirname, "Release"))
888				unset($this->_files[$file]);
889		}
890	}
891	
892	/**
893	 * Fix .net reserved words
894	 *
895	 * @param string $param
896	 * @return string
897	 */
898	private function fixParamName($param)
899	{
900		if ($param == "event")
901			return "kevent";
902		else 
903			return $param;
904	}
905}
906?>