private JMethod generateZclParseCommandImplementation(JCodeModel jModel, JDefinedClass jClusterClass, JClass jParentClass,
			ZclClusterDescriptor zclClusterDescriptor, ZclCommandDescriptor zclCommandDescriptor, boolean isServer)
			throws Exception {

		boolean useTryBlock = false;

		JMethod jMethod = jClusterClass.method(JMod.PROTECTED, IZclFrame.class, getParseCommandName(zclCommandDescriptor));

		JClass interfaceClass = getClusterConnectionClass(zclClusterDescriptor, !isServer);
		if (interfaceClass == null) {
			return jMethod;
		}

		JVar clientParam = jMethod.param(interfaceClass, "o");
		JVar inputFrame = jMethod.param(IZclFrame.class, "zclFrame");
		jMethod._throws(ApplianceException.class);

		if (!useTryBlock)
			jMethod._throws(ServiceClusterException.class);

		JBlock jBlock = jMethod.body();
		Vector zclParametersDescriptors = zclCommandDescriptor.getParametersDescriptors();

		JVar loopVar = null;

		// generates the code that parses the received command
		JInvocation jInvocation = clientParam.invoke(this.getCommandName(zclCommandDescriptor));
		for (int i = 0; i < zclParametersDescriptors.size(); i++) {
			ZclField zclParameterDescriptor = (ZclField) zclParametersDescriptors.get(i);
			JType type = jTypeForZbTypename(jModel, jParentClass._package(), zclParameterDescriptor.getType(),
					zclParameterDescriptor);

			JClass jClassZigBeeType = getZclDataTypeJClass(jModel, jClusterClass.getPackage(), jParentClass,
					zclParameterDescriptor.getType(), zclParameterDescriptor);

			if (jClassZigBeeType == null) {
				jBlock.directStatement("// FIXME: unable handle parameter '" + zclParameterDescriptor.getName() + "' of type '"
						+ zclParameterDescriptor.getType() + "'");
				continue;
			}

			JVar param;

			if (zclParameterDescriptor.isArray()) {
				JVar jVarArraySize = jBlock.decl(jModel._ref(int.class), "size");
				JInvocation parseSize = jModel.ref(ZclDataTypeUI8.class).staticInvoke("zclParse").arg(inputFrame);
				jBlock.assign(jVarArraySize, parseSize);

				param = jBlock.decl(type.array(), zclParameterDescriptor.getName());

				System.out.println(param.name());
				jBlock.directStatement(param.name() + " = new " + type.name() + "[" + jVarArraySize.name() + "];");

				if (loopVar == null) {
					loopVar = jBlock.decl(jModel._ref(int.class), "i");
				}

				JForLoop forLoop = jBlock._for();
				forLoop.test(loopVar.lt(jVarArraySize));
				forLoop.init(loopVar, JExpr.lit(0));
				forLoop.update(loopVar.incr());
				forLoop.body().assign(JExpr.ref(zclParameterDescriptor.getName()).component(loopVar),
						jClassZigBeeType.staticInvoke("zclParse").arg(inputFrame));
			} else {
				param = jBlock.decl(type, zclParameterDescriptor.getName());
				param.init(jClassZigBeeType.staticInvoke("zclParse").arg(inputFrame));
			}

			jInvocation.arg(param);
		}

		if (useDefaultRequestContext) {
			jInvocation.arg(JExpr.ref("endPoint").invoke("getDefaultRequestContext"));
		} else {
			jInvocation.arg(JExpr._null());
		}

		JClass jReturnZclType = null;
		JType jReturnType = null;

		ZclCommandDescriptor responseCommand = zclCommandDescriptor.getResponse();

		if (responseCommand != null) {
			jReturnZclType = getZclDataTypeJClass(jModel, jClusterClass.getPackage(), jParentClass, responseCommand.getName(),
					responseCommand);
			jReturnType = jTypeForZigBeeTypeName(jModel, jParentClass._package(), jParentClass, responseCommand.getName());
		}

		JVar jResultVar = null;

		JBlock jTryBody = null;

		if (useTryBlock) {
			JTryBlock jTryBlock = jBlock._try();
			jTryBlock._catch(jModel.ref(Exception.class));

			jTryBody = jTryBlock.body();
		} else {
			jTryBody = jBlock;
		}

		if ((jReturnZclType != null) && (jReturnType != null)) {
			// the exec has a non-void return type, we need to assign it
			jResultVar = jTryBody.decl(jReturnType, "r").init(jInvocation);
		} else {
			if (consumeCommandsWithoutResponse) {
				jTryBody._if(clientParam.eq(JExpr._null()))._then()._return(JExpr._null());
			}
			jTryBody.add(jInvocation);
		}

		JVar jZclResponseFrame = null;

		if (jResultVar != null) {
			// assign to size variable the response size
			JVar jSizeVar = jTryBody.decl(jModel._ref(int.class), "size").init(
					jReturnZclType.staticInvoke("zclSize").arg(jResultVar));

			// creates the zclResponseFrame variable
			jZclResponseFrame = jTryBody.decl(jModel._ref(IZclFrame.class), "zclResponseFrame");
			jZclResponseFrame.init(inputFrame.invoke("createResponseFrame").arg(jSizeVar));

			int responseCommandId = responseCommand.getId();

			jTryBody.invoke(jZclResponseFrame, "setCommandId").arg(JExpr.lit(responseCommandId));

			jTryBody.staticInvoke(jReturnZclType, "zclSerialize").arg(jZclResponseFrame).arg(jResultVar);
			jTryBody._return(jZclResponseFrame);
		}

		if (jZclResponseFrame == null)
			jBlock._return(JExpr._null());

		return jMethod;
	}