/**
	 * Generates PHP class.
	 * @return NPhpClassType
	 */
	public function generateClass($parentClass = 'NDIContainer')
	{
		unset($this->definitions[self::THIS_CONTAINER]);
		$this->addDefinition(self::THIS_CONTAINER)->setClass($parentClass);

		$this->prepareClassList();

		$class = new NPhpClassType('Container');
		$class->addExtend($parentClass);
		$class->addMethod('__construct')
			->addBody('parent::__construct(?);', array($this->expand($this->parameters)));

		$classes = $class->addProperty('classes', array());
		foreach ($this->classes as $name => $foo) {
			try {
				$classes->value[$name] = $this->sanitizeName($this->getByType($name));
			} catch (NServiceCreationException $e) {
				$classes->value[$name] = new NPhpLiteral('FALSE, //' . strstr($e->getMessage(), ':'));
			}
		}

		$meta = $class->addProperty('meta', array());
		foreach ($this->definitions as $name => $def) {
			foreach ($this->expand($def->tags) as $tag => $value) {
				$meta->value[$name][NDIContainer::TAGS][$tag] = $value;
			}
		}

		foreach ($this->definitions as $name => $def) {
			try {
				$type = ($tmp=$def->class) ? $tmp : 'object';
				$sanitized = $this->sanitizeName($name);
				if (!NPhpHelpers::isIdentifier($sanitized)) {
					throw new NServiceCreationException('Name contains invalid characters.');
				}
				if ($def->shared && $name === $sanitized) {
					$class->addDocument("@property $type \$$name");
				}
				$method = $class->addMethod(($def->shared ? 'createService' : 'create') . ucfirst($sanitized))
					->addDocument("@return $type")
					->setVisibility($def->shared || $def->internal ? 'protected' : 'public')
					->setBody($name === self::THIS_CONTAINER ? 'return $this;' : $this->generateService($name));

				foreach ($this->expand($def->parameters) as $k => $v) {
					$tmp = explode(' ', is_int($k) ? $v : $k);
					$param = is_int($k) ? $method->addParameter(end($tmp)) : $method->addParameter(end($tmp), $v);
					if (isset($tmp[1])) {
						$param->setTypeHint($tmp[0]);
					}
				}
			} catch (Exception $e) {
				throw new NServiceCreationException("Service '$name': " . $e->getMessage());
			}
		}

		return $class;
	}