private JMethod generateZclCommandImplementation(JCodeModel jModel, JDefinedClass jClusterClass, JClass jParentClass,
			ZclCommandDescriptor zclCommandDescriptor) throws Exception {

		JMethod jMethod = generateZclCommandSignature(jClusterClass, jParentClass, zclCommandDescriptor, true);
		if (jMethod == null)
			return jMethod;

		boolean oldVersion = false;

		JBlock jBlock = jMethod.body();

		if (oldVersion)
			jBlock.decl(zbDeviceClass, "device");

		JType jTypeZclFrame = jModel._ref(ZclFrame.class);

		// JVar jZclTypeVar = jBlock.decl(type, "dummy");

		if (oldVersion) {
			JVar jZclResponseFrame = jBlock.decl(jModel._ref(IZclFrame.class), "zclResponseFrame");
		}

		// JVar jVarZclFrame = jBlock.decl(jModel._ref(IZclFrame.class),
		// "zclFrame");

		JVar jVarSize = null;

		Vector zclParametersDescriptors = zclCommandDescriptor.getParametersDescriptors();

		if ((optimizeForSize) && (zclParametersDescriptors.size() == 0)) {
			// size variable is not necessary!
		} else {
			jVarSize = jBlock.decl(jModel._ref(int.class), "size").init(JExpr.lit(0));
		}

		if (oldVersion) {
			jBlock.directStatement("device = getZigBeeDevice();");
			jBlock.directStatement("if (device == null)");
			jBlock.directStatement("	throw new ApplianceException(\"Not attached\");");

			jBlock.directStatement("boolean sync = true;");
		}

		int commandId = zclCommandDescriptor.getId();

		JBlock jCalculateSizeBlock = jMethod.body().block();

		for (int i = 0; i < zclParametersDescriptors.size(); i++) {
			ZclField zclParameterDescriptor = (ZclField) zclParametersDescriptors.get(i);

			try {
				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;
				}

				if (zclParameterDescriptor.isArray()) {
					JVar methodParam = jMethod.listParams()[i];

					// TODO: optimize
					jCalculateSizeBlock.assignPlus(jVarSize,
							methodParam.ref("length").mul(jClassZigBeeType.staticInvoke("zclSize").arg(JExpr.lit(0))));

					// FIXME: the 'JExpr.lit(0)' above, must be replaced with a
					// 0 of the base type of the jClassZigBeeType
					// If this type is for intance a uint8 it must be casted to
					// (short).

					jCalculateSizeBlock.assignPlus(jVarSize, JExpr.lit(0x01));

				} else {
					jCalculateSizeBlock.assignPlus(jVarSize,
							jClassZigBeeType.staticInvoke("zclSize").arg(JExpr.ref(zclParameterDescriptor.getName())));
				}

			} catch (Exception e) {
				jCalculateSizeBlock.directStatement("// FIXME: unable handle parameter '" + zclParameterDescriptor.getName()
						+ "' of type '" + zclParameterDescriptor.getType() + "'");
			}
		}
		JVar jVarZclFrame = null;

		if (jVarSize != null) {
			// FrameType is "Cluster Specific Command"
			jVarZclFrame = jBlock.decl(jTypeZclFrame, "zclFrame").init(
					JExpr._new(jTypeZclFrame).arg(JExpr.lit(0x01)).arg(JExpr.ref("size")));
		} else {
			// Zero frame size!
			jVarZclFrame = jBlock.decl(jTypeZclFrame, "zclFrame").init(JExpr._new(jTypeZclFrame).arg(JExpr.lit(0x01)));
		}

		// jBlock.directStatement("zclFrame.setSequence(sequence++);");
		jBlock.invoke(jVarZclFrame, "setCommandId").arg(JExpr.lit(commandId));
		JBlock jSerializeBlock = jMethod.body().block();
		JVar loopVar = null;

		for (int i = 0; i < zclParametersDescriptors.size(); i++) {
			ZclField zclParameterDescriptor = (ZclField) zclParametersDescriptors.get(i);
			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;
			}

			if (zclParameterDescriptor.isArray()) {
				JVar methodParam = jMethod.listParams()[i];
				JExpression jVarArraySize = methodParam.ref("length");

				// jBlock.assignPlus(jVarSize,
				// jVarArraySize.mul(jClassZigBeeType.staticInvoke("zclSize").arg(JExpr._null())));

				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().staticInvoke(jClassZigBeeType, "zclSerialize").arg(jVarZclFrame)
						.arg(JExpr.ref(zclParameterDescriptor.getName()).component(loopVar));
			} else {
				jSerializeBlock.staticInvoke(jClassZigBeeType, "zclSerialize").arg(jVarZclFrame)
						.arg(JExpr.ref(zclParameterDescriptor.getName()));
			}
		}

		JType jReturnZclType = null;

		ZclCommandDescriptor response = zclCommandDescriptor.getResponse();

		if (response != null)
			jReturnZclType = getZclDataTypeJClass(jModel, jClusterClass.getPackage(), jParentClass, response.getName(), response);

		if (oldVersion) {
			jBlock.directStatement("if (sync) {");

			JTryBlock jTryBlockInvoke = jBlock._try();
			jTryBlockInvoke.body().directStatement("	zclResponseFrame =  device.invoke(CLUSTER_ID, zclFrame);");

			jTryBlockInvoke._catch(jModel.ref(ZigBeeException.class)).body()
					._throw(JExpr._new(jModel.ref(ApplianceException.class)).arg(JExpr.direct("INVOKE_ERROR_MESSAGE")));

			jBlock.directStatement("	if (zclResponseFrame.isClientToServer())");
			jBlock.directStatement("		throw new ApplianceException(BAD_DIRECTION_MESSAGE);");
		}

		int expectedCommandId = 0x00; // FIXME: it must be the default response
		// command id
		// response!!!!

		// FIXME: corretto?
		if (zclCommandDescriptor.getResponse() != null)
			expectedCommandId = zclCommandDescriptor.getResponse().getId();
		else
			expectedCommandId = ZCL.ZclDefaultRsp;

		JInvocation issueExec = null;

		JVar[] jParams = jMethod.listParams();
		JVar jContextParamVar = jParams[jParams.length - 1];

		if (optimizeForSize) {
			issueExec = JExpr.invoke("issueExec").arg(jVarZclFrame).arg(JExpr.lit(expectedCommandId)).arg(jContextParamVar);
		} else {
			issueExec = JExpr.invoke("issueExec").arg(jClusterClass.staticRef("CLUSTER_ID")).arg(jVarZclFrame)
					.arg(JExpr.lit(expectedCommandId)).arg(jContextParamVar);
		}

		if (jReturnZclType != null) {
			JVar jVarResponseFrame = jBlock.decl(jModel._ref(IZclFrame.class), "zclResponseFrame").init(issueExec);
			jBlock._return(JExpr.direct(jReturnZclType.name() + ".zclParse(zclResponseFrame)"));
		} else {
			jBlock.add(issueExec);
		}