diff --git a/.gitignore b/.gitignore index cddc58e..eaf591e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ # Exclude .pyc (compile python file) files *.pyc + +# Default ouptut folder +src/ +build/ +dist/ +*.egg-info +classes/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..714bbd0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: python +python: + - "2.7" + +# command to install dependencies +install: "pip install -r requirements.txt" +# command to run tests +script: nosetests \ No newline at end of file diff --git a/JavaCodeGenerator.py b/JavaCodeGenerator.py deleted file mode 100644 index cc133e5..0000000 --- a/JavaCodeGenerator.py +++ /dev/null @@ -1,443 +0,0 @@ -''' -The MIT License (MIT) - -Copyright (c) 2013 SinnerSchrader Mobile GmbH - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -''' - -import time -import datetime -import os - -class JavaCodeGenerator: - naturalList = ["Object", "String", "double", "boolean", "Double", "Boolean"] - projectPrefix = "" - dirPath = "" - memberVariables = "" - isChild = False - isAbstract = False - - def getCommonDescriptionString(self): - today = datetime.date.fromtimestamp(time.time()) - commonDescription = "/*\n * Created by MetaJSONParser on " + today.strftime("%d.%m.%Y") + "." - commonDescription += "\n * Copyright (c) " + str(today.year) + " SinnerSchrader Mobile. All rights reserved.\n*/\n" - return commonDescription - - def make(self, schemeObj): - self.makeInternal(schemeObj) - self.makeExtension(schemeObj) - return True - - def makeInternal(self, schemeObj): - self.isAbstract = True - sourceString = "" - self.isChild = False; - print "starting: " + self.getClassName(schemeObj) - - if len(self.dirPath) > 0: - sourceString += "package " + self.dirPath.replace("/", ".") + ".internal;\n\n" - sourceString += self.getCommonDescriptionString() - sourceString += self.getImports(schemeObj) - sourceString += self.getClassDefinition(schemeObj) - - methodString = ""; - self.memberVariables = "" - for prop in schemeObj.props: - methodString += self.getMethod(schemeObj, prop) - - for variable in self.memberVariables.split("\n"): - if len(variable) > 0: - sourceString += self.indent(1) + variable + ";" - - sourceString += "\n" - - setterString = ""; - getterString = ""; - for variable in self.memberVariables.split("\n"): - setterString += self.createSetter(variable) - getterString += self.createGetter(variable) - - sourceString += self.getConstructor(schemeObj) - sourceString += setterString - sourceString += getterString - - # end class body - sourceString += "}\n" - - if not os.path.exists(self.dirPath + "/internal"): - os.makedirs(self.dirPath + "/internal") - try: - sourceFile = open(self.dirPath + "/internal/" + self.getClassName(schemeObj) + ".java", "w") - sourceFile.write(sourceString) # Write a string to a file - finally: - sourceFile.close() - - def makeExtension(self, schemeObj): - sourceString = "" - self.isChild = False; - self.isAbstract = False - print "extending: " + self.getClassName(schemeObj) - - if len(self.dirPath) > 0: - sourceString += "package " + self.dirPath.replace("/", ".") + ";\n\n" - sourceString += self.getCommonDescriptionString() - sourceString += self.getImports(schemeObj) - sourceString += "import " + self.dirPath.replace("/", ".") + ".internal.Abstract" + self.getClassName(schemeObj) + ";\n" - - sourceString += "\npublic class " + self.getClassName(schemeObj) - sourceString += " extends Abstract" + self.getClassName(schemeObj) - sourceString += " {\n" - - sourceString += self.indent(1) + "public " + self.getClassName(schemeObj) + "(JSONObject json) throws JSONException {" - sourceString += self.indent(2) + "super(json);" - sourceString += self.indent(1) + "}\n" - # end class body - sourceString += "}\n" - try: - sourceFile = open(self.dirPath + "/" + self.getClassName(schemeObj) + ".java", "w") - sourceFile.write(sourceString) # Write a string to a file - finally: - sourceFile.close() - - def getClassDefinition(self, schemeObj): - abstract = "" - classDef = "\npublic class " + self.getClassName(schemeObj) - if self.isAbstract is True: - abstract = "Abstract" - classDef = "\npublic abstract class " + self.getClassName(schemeObj) - if schemeObj.base_type != "object": - self.isChild = True - classDef += " extends " + abstract + self.projectPrefix + self.cap(schemeObj.base_type) - classDef += " {\n" - return classDef - - def getMethod(self, schemeObj, prop=None): - source = "" - if len(prop.getBaseTypes()) == 0: - # only one base type - source += self.getMethodForBaseType(schemeObj, prop, prop.base_type) - else: - # multiple base types - for baseType in prop.getBaseTypes(): - if schemeObj.hasScheme(baseType): - baseTypeScheme = schemeObj.getScheme(baseType) - objectName = self.convertToJavaType(baseTypeScheme.type_name) - className = self.projectPrefix + self.cap(self.convertToJavaType(baseTypeScheme.type_name)) - if len(baseTypeScheme.getBaseTypes()) == 0: - if self.convertToJavaType(baseTypeScheme.base_type) == "array": - for subType in baseTypeScheme.sub_type: - className = self.cap(subType) - projectPrefix = "" - if schemeObj.hasScheme(subType) and len(schemeObj.getScheme(subType).props) > 0: - projectPrefix = self.projectPrefix - - self.addOrIgnoreMemberVariable("private", "ArrayList<" + projectPrefix + className + ">", self.getVariableName(prop.type_name) + "As" + className) - if prop.required is True: - source += self.indent(2) + "final JSONArray " + self.getVariableName(prop.type_name) + "As" + className + "Array = json.getJSONArray(\"" + self.getVariableName(prop.type_name) + "\");" - else: - extraIndent = " " - source += self.indent(2) + "final JSONArray " + self.getVariableName(prop.type_name) + "As" + className + "Array = json.optJSONArray(\"" + self.getVariableName(prop.type_name) + "\");" - source += self.indent(2) + "if (" + self.getVariableName(prop.type_name) + "As" + className + "Array == null) {" - source += self.indent(3) + self.getVariableName(prop.type_name) + "As" + className + " = null;" - source += self.indent(2) + "} else {" - - source += self.indent(2) + extraIndent + self.getVariableName(prop.type_name) + "As" + className + " = new ArrayList<" + projectPrefix + className + ">(" + self.getVariableName(prop.type_name) + "As" + className + "Array.length());" - source += self.indent(2) + extraIndent + "for (int i = 0; i < " + self.getVariableName(prop.type_name) + "As" + className + "Array.length(); i++) {" - if self.isNatural(className): - source += self.indent(3) + extraIndent + self.getVariableName(prop.type_name) + "As" + className + ".add(" + self.getVariableName(prop.type_name) + "As" + className + "Array.get" + className + "(i));" - else: - source += self.indent(3) + extraIndent + self.getVariableName(prop.type_name) + "As" + className + ".add(new " + projectPrefix + className + "(" + self.getVariableName(prop.type_name) + "As" + className + "Array.getJSONObject(i)));" - source += self.indent(2) + extraIndent + "}" - source += self.indent(2) + "}" - return source - variableName = self.getVariableName(prop.type_name) + "As" + self.cap(objectName) - self.addOrIgnoreMemberVariable("private", self.cap(className), variableName) - getType = "opt" - if prop.required is True: - getType = "get" - - if self.isNatural(className): - source += self.getSchemeLimitationBody(schemeObj, baseTypeScheme) - else: - source += self.indent(2) + variableName + " = new " + self.projectPrefix + self.cap(self.convertToJavaType(baseTypeScheme.type_name)) + "(json.getJSONObject(\"" + self.getVariableName(prop.type_name) + "\"));" - else: - asString = "" - if self.convertToJavaType(baseTypeScheme.base_type) == "multi": - asString = "As" + className - projectPrefix = "" - if baseTypeScheme.isNaturalType() is False: - projectPrefix = self.projectPrefix - - self.addOrIgnoreMemberVariable("private", projectPrefix + className, self.getVariableName(prop.type_name) + asString) - if prop.required is True: - source += self.indent(2) + self.getVariableName(prop.type_name) + " = new " + projectPrefix + className + "(json.getJSONObject(\"" + self.getVariableName(prop.type_name) + "\"));" - else: - source += self.indent(2) + "final JSONObject " + self.getVariableName(prop.type_name) + "JsonObject = json.optJSONObject(\"" + self.getVariableName(prop.type_name) + "\");" - source += self.indent(2) + "if (" + self.getVariableName(prop.type_name) + "JsonObject == null) {" - source += self.indent(3) + "return null;" - source += self.indent(2) + "} else {" - source += self.indent(3) + self.getVariableName(prop.type_name) + " = new " + projectPrefix + className + "(" + self.getVariableName(prop.type_name) + "JsonObject);" - source += self.indent(2) + "}" - else: - className = self.convertToJavaType(baseType) - variableName = self.getVariableName(prop.type_name) + "As" + self.cap(className) - if self.low(className) == "byte": - self.addOrIgnoreMemberVariable("private", "byte[]", variableName) - else: - self.addOrIgnoreMemberVariable("private", self.cap(className), variableName) - - getType = "opt" - if prop.required is True: - getType = "get" - - if self.isNatural(baseType): - source += self.indent(2) + variableName + " = json." + getType + self.cap(className) + "(\"" + self.getVariableName(prop.type_name) + "\");" - else: - if self.low(className) == "date": - source += self.indent(2) + variableName + " = new Date(json." + getType + "Long(\"" + self.getVariableName(prop.type_name) + "\"));" - elif self.low(className) == "byte": - source += self.indent(2) + variableName + " = json." + getType + "String(\"" + self.getVariableName(prop.type_name) + "\").getBytes();" - else: - source += self.indent(2) + variableName + " = json." + getType + self.cap(className) + "(\"" + self.getVariableName(prop.type_name) + "\");" - return source - - def getSchemeLimitationBody(self, schemeObj, prop): - className = self.convertToJavaType(prop.base_type) - varName = self.getVariableName(prop.type_name) - source = self.indent(2) + varName + " = json.get" + className + "(\"" + varName + "\");" - if prop.base_type == "array": - if prop.hasMaxCount: - source += self.indent(2) + "if (" + varName + ".length < " + str(prop.minCount) + ") {" - source += self.indent(3) + "throw new IllegalArgumentException(\"" + varName + " can't be less than " + str(prop.minCount) + "\");" - source += self.indent(2) + "}" - if prop.hasMaxCount: - source += self.indent(2) + "if (" + varName + ".length > " + str(prop.maxCount) + ") {" - source += self.indent(3) + "throw new IllegalArgumentException(\"" + varName + " can't be bigger than " + str(prop.maxCount) + "\");" - source += self.indent(2) + "}" - if prop.hasMinLength: - source += self.indent(2) + "if (" + varName + ".length() < " + str(prop.minLength) + ") {" - source += self.indent(3) + "throw new IllegalArgumentException(\"" + varName + " can't be shorter than " + str(prop.minLength) + "\");" - source += self.indent(2) + "}" - if prop.hasMaxLength: - source += self.indent(2) + "if (" + varName + ".length() > " + str(prop.maxLength) + ") {" - source += self.indent(3) + "throw new IllegalArgumentException(\"" + varName + " can't be longer than " + str(prop.maxLength) + "\");" - source += self.indent(2) + "}" - if prop.regex: - source += self.indent(2) + "if (!Pattern.compile(\"" + prop.regex + "\").matcher(" + varName + ").matches()) {" - source += self.indent(3) + "throw new IllegalArgumentException(\"" + varName + " doesn't fit regex " + prop.regex + "\");" - source += self.indent(2) + "}" - - source += self.indent(2) + "return " + varName + ";" - return source - - def getMethodForBaseType(self, schemeObj, prop, typeName): - source = "" - baseType = typeName - typeClassName = self.cap(self.convertToJavaType(typeName)) - if baseType == "array": - for subType in prop.sub_type: - objectName = self.convertToJavaType(subType) - className = self.cap(objectName) - projectPrefix = "" - if schemeObj.hasScheme(subType) and len(schemeObj.getScheme(subType).props) > 0: - projectPrefix = self.projectPrefix - - variableName = self.getVariableName(prop.type_name) + "As" + self.cap(subType) - - self.addOrIgnoreMemberVariable("private", "ArrayList<" + projectPrefix + className + ">", variableName) - extraIndent = "" - if prop.required is True: - source += self.indent(2) + "final JSONArray " + variableName + "Array = json.getJSONArray(\"" + self.getVariableName(prop.type_name) + "\");" - else: - extraIndent = " " - source += self.indent(2) + "final JSONArray " + variableName + "Array = json.optJSONArray(\"" + self.getVariableName(prop.type_name) + "\");" - source += self.indent(2) + "if (" + variableName + "Array == null) {" - source += self.indent(3) + variableName + " = null;" - source += self.indent(2) + "} else {" - - source += self.indent(2) + extraIndent + variableName + " = new ArrayList<" + projectPrefix + className + ">(" + variableName + "Array.length());" - source += self.indent(2) + extraIndent + "for (int i = 0; i < " + variableName + "Array.length(); i++) {" - if self.isNatural(className): - if className == "Object": - className = "" - source += self.indent(3) + extraIndent + variableName + ".add(" + variableName + "Array.get" + className + "(i));" - else: - source += self.indent(3) + extraIndent + variableName + ".add(new " + projectPrefix + className + "(" + variableName + "Array.getJSONObject(i)));" - source += self.indent(2) + extraIndent + "}" - source += self.indent(2) + "}" - elif baseType == "date": - self.addOrIgnoreMemberVariable("private", self.cap(self.convertToJavaType(prop.rootBaseType())), self.getVariableName(prop.type_name)) - if prop.required is True: - source += self.indent(2) + self.getVariableName(prop.type_name) + " = new Date(json.getInt(\"" + self.getVariableName(prop.type_name) + "\") / 1000);" - else: - source += self.indent(2) + "final int " + self.getVariableName(prop.type_name) + "Timestamp = json.optInt(\"" + self.getVariableName(prop.type_name) + "\", -1);" - source += self.indent(2) + "if (" + self.getVariableName(prop.type_name) + "Timestamp == -1) {" - source += self.indent(3) + self.getVariableName(prop.type_name) + " = null;" - source += self.indent(2) + "} else {" - source += self.indent(3) + self.getVariableName(prop.type_name) + " = new Date(" + self.getVariableName(prop.type_name) + "Timestamp / 1000);" - source += self.indent(2) + "}" - else: - if self.isNatural(prop.rootBaseType()) is True: - self.addOrIgnoreMemberVariable("private", self.cap(self.convertToJavaType(prop.rootBaseType())), self.getVariableName(prop.type_name)) - getMethod = typeClassName - if getMethod == "Object": - getMethod = "" # reset as the getter for Object is just json.get() - if prop.required is True: - source += self.indent(2) + self.getVariableName(prop.type_name) + " = json.get" + getMethod + "(\"" + self.getVariableName(prop.type_name) + "\");" - else: - if len(getMethod) == 0: - source += self.indent(2) + self.getVariableName(prop.type_name) + " = json.opt" + getMethod + "(\"" + self.getVariableName(prop.type_name) + "\");" - else: - source += self.indent(2) + self.getVariableName(prop.type_name) + " = json.opt" + getMethod + "(\"" + self.getVariableName(prop.type_name) + "\", " + str(self.getDefaultValue(typeClassName)) + ");" - else: - self.addOrIgnoreMemberVariable("private", self.projectPrefix + self.cap(typeName), self.getVariableName(prop.type_name)) - typeName = self.convertToJavaType(prop.base_type); - if prop.required is True: - source += self.indent(2) + self.getVariableName(prop.type_name) + " = new " + self.projectPrefix + self.cap(typeName) + "(json.getJSONObject(\"" + self.getVariableName(prop.type_name) + "\"));" - else: - source += self.indent(2) + "final JSONObject " + self.getVariableName(prop.type_name) + "Json = json.optJSONObject(\"" + self.getVariableName(prop.type_name) + "\");" - source += self.indent(2) + "if (" + self.getVariableName(prop.type_name) + "Json == null) {" - source += self.indent(3) + self.getVariableName(prop.type_name) + " = null;" - source += self.indent(2) + "} else {" - source += self.indent(3) + self.getVariableName(prop.type_name) + " = new " + self.projectPrefix + self.cap(typeName) + "(" + self.getVariableName(prop.type_name) + "Json);" - source += self.indent(2) + "}" - - return source - - def getImports(self, schemeObj): - source = "\nimport org.json.JSONObject;" - source += "\nimport org.json.JSONArray;" - source += "\nimport org.json.JSONException;" - source += "\nimport java.util.ArrayList;" - source += "\nimport java.util.Date;" # somehow date will not be added later - temporary static import - source += "\nimport " + self.dirPath.replace("/", ".") + ".*;" - source += "\n\nimport java.lang.IllegalArgumentException;\n" - stringImported = False - dateImported = False - regexImported = False - for prop in schemeObj.props: - baseTypes = schemeObj.getScheme(schemeObj.getScheme(prop.type_name).type_name).getBaseTypes() - if prop.base_type == "string" and stringImported is False: - source += "import java.lang.String;\n" - stringImported = True - if prop.base_type == "date" and dateImported is False: - source += "import java.util.Date;\n" - dateImported = True - for baseType in baseTypes: - if not schemeObj.hasScheme(baseType): - continue - else: - base = schemeObj.getScheme(baseType) - if len(base.regex) > 0 and regexImported is False: - source += "import java.util.regex.Pattern;\n" - regexImported = True - return source - - def getConstructor(self, schemeObj): - source = self.indent(1) + "public " + self.cap(self.getClassName(schemeObj)) + "(JSONObject json) throws JSONException {" - if self.isChild: - source += self.indent(2) + "super(json);" - else: - source += self.indent(2) + "if (json == null) {" - source += self.indent(3) + "throw new IllegalArgumentException(\"JSONObject can't be null\");" - source += self.indent(2) + "}" - for prop in schemeObj.props: - source += self.getMethod(schemeObj, prop) - source += self.indent(1) + "}\n" - return source - - ### helper methods - def cap(self, name): - return name[0].capitalize() + name[1:] - - def low(self, name): - return name[0].lower() + name[1:] - - def indent(self, size): - i = 0 - indent = "\n" - while i < size: - indent += " " - i += 1 - return indent - - def convertToJavaType(self, objCType): - if objCType == "number": - return "double" - elif objCType == "any": - return "Object" - elif objCType == "data": - return "byte" - elif objCType == "string": - return "String" - elif objCType == "date": - return "Date" - else: - return objCType - - def isNatural(self, objectType): - objectType = self.convertToJavaType(objectType) - return objectType in self.naturalList - - def getDefaultValue(self, type): - typeName = self.low(self.convertToJavaType(type)) - if typeName == "double": - return 0 - elif typeName == "boolean": - return "false" - return "null" - - def addOrIgnoreMemberVariable(self, visibility, type, name): - newVariable = visibility + " " + type + " " + name + "" - - if not newVariable in self.memberVariables.split("\n"): - self.memberVariables += newVariable + "\n" - - def createMethodHead(self, visibility, returnType, name, parameter = ""): - return self.indent(1) + visibility + " " + returnType + " " + name + "(" + parameter + ") {" - - def createSetter(self, variableString): - elements = variableString.split(" ") - if len(elements) == 3: - source = self.createMethodHead("public", "void", "set" + self.cap(elements[2]), elements[1] + " " + self.low(elements[2])) - source += self.indent(2) + "this." + elements[2] + " = " + self.low(elements[2]) + ";" - source += self.indent(1) + "}\n" - return source - return "" - - def createGetter(self, variableString): - elements = variableString.split(" ") - if len(elements) == 3: - source = self.createMethodHead("public", elements[1], "get" + self.cap(elements[2])) - source += self.indent(2) + "return " + elements[2] + ";" - source += self.indent(1) + "}\n" - return source - return "" - - def getClassName(self, schemeObj): - if self.isAbstract is True: - return "Abstract" + schemeObj.getClassName() - else: - return schemeObj.getClassName() - - def getVariableName(self, name): - if name in ["private", "protected", "public", "class", "abstract", "final", "static"]: - return self.projectPrefix + self.cap(name) - return name \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..176eb63 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include metajson/templates * diff --git a/ObjectiveCCodeGenerator.py b/ObjectiveCCodeGenerator.py deleted file mode 100755 index 346072f..0000000 --- a/ObjectiveCCodeGenerator.py +++ /dev/null @@ -1,1032 +0,0 @@ -''' -The MIT License (MIT) - -Copyright (c) 2013 SinnerSchrader Mobile GmbH - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -''' - -import datetime, time, os - -class ObjectiveCCodeGenerator : - - projectPrefix = "" - dirPath = "" - - def __init__(self): - projectPrefix = "" - dirPath = "classes" - - - def getCommonDescriptionString(self) : - today = datetime.date.fromtimestamp(time.time()) - commonDescription = "//\n// Created by MetaJSONParser." - commonDescription += "\n// Copyright (c) "+ str(today.year) +" SinnerSchrader Mobile. All rights reserved.\n\n" - return commonDescription - - def getHeaderDescriptionString(self, name) : - hDescriptionString = "//\n// "+ self.getTitledString(name) +".h\n" - hDescriptionString += self.getCommonDescriptionString() - return hDescriptionString - - def getSourceDescriptionString(self, name) : - mDescriptionString = "//\n// "+ self.getTitledString(name) +".m\n" - mDescriptionString += self.getCommonDescriptionString() - return mDescriptionString - - def makeVarName(self,schemeObj) : - returnName = schemeObj.type_name - if str(schemeObj.type_name) == "id" or str(schemeObj.type_name) == "description" : - titleName = schemeObj.type_name.upper() - titleName = titleName[:1] + schemeObj.type_name[1:] - returnName = self.projectPrefix.lower() + titleName - else : - prefixes = ["new", "alloc", "copy"] - for prefix in prefixes: - if schemeObj.type_name.startswith(prefix): - titleName = schemeObj.type_name.upper() - titleName = titleName[:1] + schemeObj.type_name[1:] - returnName = self.projectPrefix.lower() + titleName - #print returnName - break - - return returnName - - def make(self, schemeObj) : - headerString = "" - sourceString = "" - - hDescriptionString = self.getHeaderDescriptionString(schemeObj.getMachineClassName()) - mDescriptionString = self.getSourceDescriptionString(schemeObj.getMachineClassName()) - - hIncludeHeaders = "#import \n" - mIncludeHeaders = "#import \"" + self.projectPrefix + "APIParser.h\"\n" - mIncludeHeaders += "#import \"NSString+RegExValidation.h\"\n" - mIncludeHeaders += "#import \"" + schemeObj.getClassName() +".h\"\n" - predefineCalsses = "" - interfaceDefinition = "@class " + schemeObj.getClassName() + ";\n\n" - interfaceDefinition += "@interface " + schemeObj.getMachineClassName() - interfaceImplementation = "@implementation " + schemeObj.getMachineClassName() + "\n" - propertyDefinition = "" - methodDefinition = "" - initMethodString = "" - - factoryMethodImpl = "\n+ (" + schemeObj.getClassName() +" *)" + self.makeVarName(schemeObj) + "WithDictionary:(NSDictionary *)dic withError:(NSError **)error {\n" - factoryMethodImpl += " return [[" + schemeObj.getClassName() + " alloc] initWithDictionary:dic withError:error];\n" - factoryMethodImpl += "}\n\n" - - descriptionMethodString = "- (NSString *)description {\n return [NSString stringWithFormat:@\"%@\",[self propertyDictionary]];\n}\n" - propertyDictionaryString = "- (NSDictionary *)propertyDictionary {\n" - - encodeMethodString = "- (void)encodeWithCoder:(NSCoder*)coder {\n" - decodeMethodString = "- (id)initWithCoder:(NSCoder *)coder {\n" - - """ - check base type - """ - if schemeObj.isNaturalType() or schemeObj.rootBaseType() == "any": - print "error : ", schemeObj.base_type ," (" , schemeObj.type_name, ") is natural type. Cannot make source code for it.\n" - return False - if schemeObj.rootBaseType() != "object" : - print "error : ", schemeObj.base_type ," (" , schemeObj.type_name,") is not custom 'object' type.\n" - return False - - if len(schemeObj.props) == 0 : - # don't make source codes. - print "NO Property : " + schemeObj.getMachineClassName() - - if schemeObj.base_type != "object" : - - encodeMethodString += " [super encodeWithCoder:coder];\n" - decodeMethodString += " self = [super initWithCoder:coder];\n" - propertyDictionaryString += " NSDictionary *parentDic = [super propertyDictionary];\n" - propertyDictionaryString += " NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithDictionary:parentDic];\n" - - #print "(make : !object) : find scheme : " + schemeObj.base_type + " from : " + schemeObj.type_name - if schemeObj.hasScheme(schemeObj.base_type) : - parentSchemeObj = schemeObj.getScheme(schemeObj.base_type) - hIncludeHeaders += "#import \"" + parentSchemeObj.getClassName() + ".h\"\n" - interfaceDefinition += " : " + parentSchemeObj.getClassName() + "\n" - initMethodString = "- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error {\n self = [super initWithDictionary:dic withError:error];\n" - else : - print "error : ", schemeObj.base_type, "(parent type of ", schemeObj.type_name ,") is not defined.\n" - return False - else : - decodeMethodString += " self = [super init];\n" - interfaceDefinition += " : NSObject \n" - initMethodString = "- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error {\n self = [super init];\n" - propertyDictionaryString += " NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];\n" - - initMethodString += " if (self) {\n" - interfaceDefinition += "\n" - #factory method - methodDefinition += "+ (" + schemeObj.getClassName() +" *)" + self.makeVarName(schemeObj) + "WithDictionary:(NSDictionary *)dic withError:(NSError **)error;\n" - #initialize - methodDefinition += "- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error;\n" - #property dictionary method - methodDefinition += "- (NSDictionary *)propertyDictionary;\n" - getterMethodImplementation = "" - - - """ - check properties - """ - otherClasses = {} - for propObj in schemeObj.props : - if propObj.type_description and len(propObj.type_description) : - propertyDefinition += "// " + propObj.type_description + "\n" - propertyDefinition += self.propertyDefinitionString(propObj) - - decodeMethodString += self.propertyDecodeString(propObj, 1) - encodeMethodString += self.propertyEncodeString(propObj, 1) - propertyDictionaryString += self.setPropertyDictionaryString(propObj, "dic", 1) - - subTypeSchemeList = propObj.getSubType() - if propObj.rootBaseType() == "array" and len(subTypeSchemeList) == 1 and not "any" in subTypeSchemeList: - subTypeSchemeName = subTypeSchemeList[0] - tmpArrayName = "tmp" + self.getTitledString(propObj.type_name) + "Array" - initMethodString += self.getNaturalTypeGetterFromDictionaryCode(propObj, "NSArray *", tmpArrayName, "dic", propObj.type_name, (propObj.required != True), 2, "self") - initMethodString += self.getNaturalTypeValidationCode(propObj, tmpArrayName, 2, "self") - tmpMutableArrayName = "tmp" + self.getTitledString(propObj.type_name) - initMethodString += " NSMutableArray *" + tmpMutableArrayName + " = [[NSMutableArray alloc] initWithCapacity:" + tmpArrayName + ".count];\n" - - initMethodString += " for (NSUInteger loop = 0; loop < " + tmpArrayName + ".count; loop++) {\n" - subTypeSchemeObj = propObj.getScheme(subTypeSchemeName) - - if subTypeSchemeName in propObj.naturalTypeList : - initMethodString += self.getNaturalTypeGetterFromArrayCode(subTypeSchemeName, self.getNaturalTypeClassString(subTypeSchemeName), "tmpValue", tmpArrayName, "loop", (propObj.required != True), 3, "self") - initMethodString += " if (tmpValue) {\n" - initMethodString += " [" + tmpMutableArrayName + " addObject:tmpValue];\n" - initMethodString += " }\n" - elif subTypeSchemeObj and subTypeSchemeObj.isNaturalType() : - initMethodString += self.getNaturalTypeGetterFromArrayCode(subTypeSchemeName, self.getNaturalTypeClassString(subTypeSchemeObj.rootBaseType()), "tmpValue", tmpArrayName, "loop", (propObj.required != True), 3, "self") - if subTypeSchemeObj : - initMethodString += self.getNaturalTypeValidationCode(subTypeSchemeObj, "tmpValue", 3, "self") - initMethodString += " if (tmpValue) {\n" - initMethodString += " [" + tmpMutableArrayName + " addObject:tmpValue];\n" - initMethodString += " }\n" - elif subTypeSchemeObj and subTypeSchemeObj.rootBaseType() == "object" : - tmpDicName = "tmpDic" - initMethodString += self.getDictionaryGetterFromArrayCode(tmpDicName, tmpArrayName, "loop", False, 3, "self") - initMethodString += " " + subTypeSchemeObj.getClassName() + "*tmpObject = nil;\n" - initMethodString += self.getObjectAllocatorFromDictionaryCode(False, subTypeSchemeObj.getClassName(), "tmpObject", tmpDicName, (propObj.required != True), 3, "self") - initMethodString += " if (tmpObject) {\n" - initMethodString += " [" + tmpMutableArrayName + " addObject:tmpObject];\n" - initMethodString += " }\n" - else : - print "Error : can't handle subType of " + propObj.type_name - return False - - initMethodString += " }\n" - initMethodString += " self." + self.makeVarName(propObj) + " = [NSArray arrayWithArray:" + tmpMutableArrayName + "];\n" - - elif propObj.isNaturalType() : - initMethodString += self.getNaturalTypeGetterFromDictionaryCode(propObj, "", "self." + self.makeVarName(propObj), "dic", propObj.type_name, (propObj.required != True), 2, "self") - initMethodString += self.getNaturalTypeValidationCode(propObj, "self." + self.makeVarName(propObj), 2, "self") - if len(subTypeSchemeList) > 1 or "any" in subTypeSchemeList : - pass - else : - continue - - elif propObj.rootBaseType() == "object" : - if otherClasses.has_key(propObj.type_name) == False : - otherClasses[propObj.type_name] = propObj - tmpVarName = "tmp"+self.getTitledString(propObj.type_name) - initMethodString += self.getDictionaryGetterFromDictionaryCode(tmpVarName, "dic", propObj.type_name, (propObj.required != True), 2, "self") - initMethodString += self.getObjectAllocatorFromDictionaryCode(False, propObj.getClassName(), "self." + self.makeVarName(propObj), tmpVarName, (propObj.required != True), 2, "self") - continue - - else : - tmpVarName = "tmp" + self.getTitledString(propObj.type_name) - initMethodString += self.getGetterFromDictionaryCode("id ", tmpVarName, "dic", propObj.type_name, (propObj.required != True), 2, "self") - initMethodString += " if ("+ tmpVarName +") {\n" - initMethodString += self.getDictionaryAllocatorCode(False, "self." + self.makeVarName(propObj), tmpVarName, propObj.type_name, 3, "self") - initMethodString += " }\n" - - if propObj.rootBaseType() == "array" and len(subTypeSchemeList) == 1 and not "any" in subTypeSchemeList: - pass - else : - for methodDefinitionString in self.getterMethodDefinitionString(propObj) : - methodDefinition += methodDefinitionString - getterMethodImplementation += self.getterMethodString(propObj); - - if propObj.rootBaseType() == "multi" : - for multiTypeScheme in propObj.getBaseTypes() : - if multiTypeScheme in propObj.naturalTypeList or multiTypeScheme == "any" : - continue - #print "(make : property multi) : find scheme : " + multiTypeScheme + " from : " + propObj.type_name - elif schemeObj.hasScheme(multiTypeScheme) == False : - print "Warning : " + propObj.type_name + " in " + propObj.getDomainString() + " (multi) has undefined base-type." - print " undefined type : " + multiTypeScheme - continue - multiTypeSchemeObj = propObj.getScheme(multiTypeScheme) - - if multiTypeSchemeObj.rootBaseType() == "object" and otherClasses.has_key(multiTypeScheme) == False: - otherClasses[multiTypeScheme] = multiTypeSchemeObj - elif propObj.rootBaseType() == "any" : - pass - - elif propObj.rootBaseType() == "array" : - for subTypeScheme in propObj.getSubType() : - if subTypeScheme in propObj.naturalTypeList or subTypeScheme == "any" : - continue - #print "(make : property array) : find scheme : " + subTypeScheme + " from : " + propObj.type_name - elif propObj.hasScheme(subTypeScheme) == False: - print "Warning : " + propObj.type_name + " in " + propObj.getDomainString() + " (array) has undefined sub type." - print " undefined type : " + multiTypeScheme - continue - subTypeSchemeObj = propObj.getScheme(subTypeScheme) - if subTypeSchemeObj.rootBaseType() == "object" and otherClasses.has_key(subTypeSchemeObj.type_name) == False : - otherClasses[subTypeSchemeObj.type_name] = subTypeSchemeObj - - encodeMethodString += "}\n" - decodeMethodString += " return self;\n}\n" - propertyDictionaryString += " return dic;\n}\n" - otherClassNameList = [] - otherClassList = [] - for otherClassName in otherClasses : - otherClassObject = otherClasses[otherClassName] - if not otherClassObject.getClassName() in otherClassNameList : - otherClassList.append(otherClassObject) - otherClassNameList.append(otherClassObject.getClassName()) - - for includeTypeObj in otherClassList : - predefineCalsses += "@class " + includeTypeObj.getClassName() + ";\n" - mIncludeHeaders += "#import \""+ includeTypeObj.getClassName() + ".h\"\n" - if len(includeTypeObj.props) and includeTypeObj.rootBaseType() == "object" : - self.make(includeTypeObj) - - initMethodString += " }\n" + " return self;\n}\n\n" - interfaceDefinition += "\n" + propertyDefinition + "\n" + methodDefinition + "\n@end\n" - - interfaceImplementation += "\n#pragma mark - factory\n" + factoryMethodImpl - interfaceImplementation += "\n#pragma mark - initialize\n" + initMethodString - interfaceImplementation += "\n#pragma mark - getter\n" + getterMethodImplementation - interfaceImplementation += "\n#pragma mark - NSCoding\n" + encodeMethodString + decodeMethodString - interfaceImplementation += "\n#pragma mark - Object Info\n" + propertyDictionaryString + descriptionMethodString +"\n@end\n" - headerString += hDescriptionString + hIncludeHeaders + "\n" - - if len(predefineCalsses) > 0 : - headerString += predefineCalsses + "\n" - - headerString += interfaceDefinition + "\n" - sourceString += mDescriptionString + mIncludeHeaders + "\n\n" + interfaceImplementation - - if not os.path.exists(self.dirPath): - os.makedirs(self.dirPath) - - if self.dirPath.endswith("/") : - self.dirPath = self.dirPath[:-1] - - if not os.path.exists(self.dirPath + "/AbstractInterfaceFiles/"): - os.makedirs(self.dirPath + "/AbstractInterfaceFiles/") - - #machine file - #print headerString - try: - headerFile = open(self.dirPath + "/AbstractInterfaceFiles/" + schemeObj.getMachineClassName() + ".h", "w") - print "create " + self.dirPath + "/AbstractInterfaceFiles/" + schemeObj.getMachineClassName() + ".h" + " file..." - headerFile.write(headerString) # Write a string to a file - finally : - headerFile.close() - - #print sourceString - try: - sourceFile = open(self.dirPath + "/AbstractInterfaceFiles/" + schemeObj.getMachineClassName() + ".m", "w") - print "create " + self.dirPath + "/AbstractInterfaceFiles/" + schemeObj.getMachineClassName() + ".m" + " file..." - sourceFile.write(sourceString) # Write a string to a file - finally : - sourceFile.close() - - - #customizable file - customizableInterface = self.getHeaderDescriptionString(schemeObj.getClassName()) - customizableInterface += "#import \"" + schemeObj.getMachineClassName() +".h\"\n" - customizableInterface += "@interface " + schemeObj.getClassName() + " : " + schemeObj.getMachineClassName() + "\n\n@end\n\n" - - customizableImplementation = self.getSourceDescriptionString(schemeObj.getClassName()) - customizableImplementation += "#import \"" + schemeObj.getClassName() +".h\"\n" - customizableImplementation += "@implementation " + schemeObj.getClassName() + "\n\n@end\n\n" - - - #print headerString - customizableInterfaceFileName = self.dirPath + "/" + schemeObj.getClassName() + ".h" - if os.path.isfile(customizableInterfaceFileName) is False : - print "create " + customizableInterfaceFileName + " file..." - try: - headerFile = open(customizableInterfaceFileName, "w") - headerFile.write(customizableInterface) # Write a string to a file - finally : - headerFile.close() - - #print sourceString - customizableImplementationFileName = self.dirPath + "/" + schemeObj.getClassName() + ".m" - if os.path.isfile(customizableImplementationFileName) is False : - print "create " + customizableImplementationFileName + " file..." - try: - sourceFile = open(customizableImplementationFileName, "w") - sourceFile.write(customizableImplementation) # Write a string to a file - finally : - sourceFile.close() - - return True - - - """ - getter method - """ - def getterMethodDefinitionStringInDictionary(self, returnTypeName, typeName, typeTitle, postFix) : - return "- (" + returnTypeName + ")" + typeName + "As" + typeTitle + postFix - - def getterMethodDefinitionStringInArray(self, returnTypeName, typeName, arrayName, postFix) : - return "- (" + returnTypeName + ")" + typeName + "In"+ arrayName + postFix - - def getTitledString(self, inputString) : - titledString = inputString.upper() - titledString = titledString[:1] + inputString[1:] - return titledString - - def getNaturalTypeClassTitleString(self,typeName) : - titleString = self.getTitledString(typeName) - if typeName == "boolean" or typeName == "string" or typeName == "date" or typeName == "data" or typeName == "number" or typeName == "array" : - return titleString - else : - return "Object" - - def getNaturalTypeClassString(self,typeName) : - if typeName == "boolean" : - return "BOOL " - elif typeName == "string" : - return "NSString *" - elif typeName == "date" : - return "NSDate *" - elif typeName == "data" : - return "NSData *" - elif typeName == "number" : - return "NSNumber *" - elif typeName == "array" : - return "NSArray *" - else : - return "id " - - def getterMethodDefinitionString(self, schemeObj) : - resultStringList= [] - - titleName = schemeObj.type_name.upper() - titleName = titleName[:1] + schemeObj.type_name[1:] - postFix = ":(NSError **)error;\n" - - if schemeObj.rootBaseType() == "multi" : - for schemeName in schemeObj.getBaseTypes() : - #print "(getterMethodDefinitionString : multi) : find scheme : " + schemeName + " from : " + schemeObj.type_name - if schemeObj.hasScheme(schemeName) : - baseSubTypeSchemeObj = schemeObj.getScheme(schemeName) - baseSubTypeTitle = baseSubTypeSchemeObj.type_name.upper() - baseSubTypeTitle = baseSubTypeTitle[:1] + baseSubTypeSchemeObj.type_name[1:] - - if baseSubTypeSchemeObj.isNaturalType() == False : - resultStringList.append(self.getterMethodDefinitionStringInDictionary(baseSubTypeSchemeObj.getClassName() + " *", schemeObj.type_name, baseSubTypeSchemeObj.getClassName(), postFix)) - else : - resultStringList.append(self.getterMethodDefinitionStringInDictionary(self.getNaturalTypeClassString(baseSubTypeSchemeObj.rootBaseType()), schemeObj.type_name, baseSubTypeTitle, postFix)) - - elif schemeName == "any" : - resultStringList.append(self.getterMethodDefinitionStringInDictionary("id", schemeObj.type_name, "Object", postFix)) - else : - resultStringList.append(self.getterMethodDefinitionStringInDictionary(self.getNaturalTypeClassString(schemeName), schemeObj.type_name, self.getNaturalTypeClassTitleString(schemeName),postFix)) - - elif schemeObj.rootBaseType() == "array" : - postFix = "AtIndex:(NSUInteger)index withError:(NSError **)error;\n"; - for schemeName in schemeObj.getSubType() : - #print "(getterMethodDefinitionString : array) : find scheme : " + schemeName + " from : " + schemeObj.type_name - if schemeObj.hasScheme(schemeName) : - baseSubTypeSchemeObj = schemeObj.getScheme(schemeName) - - if baseSubTypeSchemeObj.isNaturalType() == False : - resultStringList.append(self.getterMethodDefinitionStringInArray(baseSubTypeSchemeObj.getClassName() + " *", baseSubTypeSchemeObj.type_name, titleName, postFix)) - else : - resultStringList.append(self.getterMethodDefinitionStringInArray(self.getNaturalTypeClassString(baseSubTypeSchemeObj.rootBaseType()), baseSubTypeSchemeObj.type_name, titleName, postFix)) - - elif schemeName == "any" : - resultStringList.append(self.getterMethodDefinitionStringInArray("id", "object", titleName, postFix)) - else : - resultStringList.append(self.getterMethodDefinitionStringInArray(self.getNaturalTypeClassString(schemeName), schemeName, titleName, postFix)) - - elif schemeObj.base_type == "any" : - resultStringList.append(self.getterMethodDefinitionStringInDictionary("id", schemeObj.type_name, "Object", postFix)) - - elif schemeObj.isNaturalType() : - print "Error : " + schemeObj.type_name + " is Natural type. don't need to define getter method.\n" - resultStringList = [] - - else : - print "Error : " + schemeObj.type_name + " is Custom Object type. don't need to define getter method.\n" - resultStringList = [] - - return resultStringList - - def getterMethodString(self, schemeObj) : - resultString = "" - postFix = ":(NSError **)error {\n" - titleName = schemeObj.type_name.upper() - titleName = titleName[:1] + schemeObj.type_name[1:] - tmpVarName = "tmp" + self.getTitledString(schemeObj.type_name) - selfDicName = "self." + self.makeVarName(schemeObj) - - if schemeObj.rootBaseType() == "multi" : - for schemeName in schemeObj.getBaseTypes() : - #print "(getterMethodString : multi) : find scheme : " + schemeName + " from : " + schemeObj.type_name - if schemeObj.hasScheme(schemeName) : - baseSubTypeSchemeObj = schemeObj.getScheme(schemeName) - baseSubTypeTitle = baseSubTypeSchemeObj.type_name.upper() - baseSubTypeTitle = baseSubTypeTitle[:1] + baseSubTypeSchemeObj.type_name[1:] - - if baseSubTypeSchemeObj.isNaturalType() == False : - tmpDicName = "tmp" + self.getTitledString(schemeObj.type_name) + "Dic" - resultString += self.getterMethodDefinitionStringInDictionary(baseSubTypeSchemeObj.getClassName() + " *", schemeObj.type_name, baseSubTypeSchemeObj.getClassName(), postFix) - resultString += self.getDictionaryGetterFromDictionaryCode(tmpDicName, selfDicName, schemeObj.type_name, (schemeObj.required != True), 1, "nil") - resultString += self.getHandleErrorCode( tmpDicName +" == nil", "", "nil", 1) - resultString += " " + baseSubTypeSchemeObj.getClassName() + " *" + tmpVarName + " = nil;\n" - resultString += self.getObjectAllocatorFromDictionaryCode(False, baseSubTypeSchemeObj.getClassName(), tmpVarName, tmpDicName, (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - else : - resultString += self.getterMethodDefinitionStringInDictionary(self.getNaturalTypeClassString(baseSubTypeSchemeObj.rootBaseType()), schemeObj.type_name, baseSubTypeTitle, postFix) - resultString += self.getNaturalTypeGetterFromDictionaryCode(baseSubTypeSchemeObj, self.getNaturalTypeClassString(baseSubTypeSchemeObj.rootBaseType()), tmpVarName, selfDicName, schemeObj.type_name, (schemeObj.required != True), 1, "nil") - resultString += self.getHandleErrorCode( tmpVarName +" == nil", "", "nil", 1) - resultString += self.getNaturalTypeValidationCode(baseSubTypeSchemeObj, tmpVarName, 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - - elif schemeName == "any" : - resultString += self.getterMethodDefinitionStringInDictionary("id", schemeObj.type_name, "Object", postFix) - resultString += self.getUndefinedTypeGetterFromDictionaryCode("id ", tmpVarName, selfDicName, schemeObj.type_name, (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - else : - resultString += self.getterMethodDefinitionStringInDictionary(self.getNaturalTypeClassString(schemeName), schemeObj.type_name, self.getNaturalTypeClassTitleString(schemeName),postFix) - resultString += self.getNaturalTypeGetterFromDictionaryCode(schemeName, self.getNaturalTypeClassString(schemeName), tmpVarName, selfDicName, schemeObj.type_name, (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - - elif schemeObj.rootBaseType() == "array" : - postFix = "AtIndex:(NSUInteger)index withError:(NSError **)error {\n"; - for schemeName in schemeObj.getSubType() : - if schemeObj.hasScheme(schemeName) : - #print "(getterMethodString : array) : find scheme : " + schemeName + " from : " + schemeObj.type_name - baseSubTypeSchemeObj = schemeObj.getScheme(schemeName) - - if baseSubTypeSchemeObj.isNaturalType() == False : - tmpDicName = "tmp" + self.getTitledString(schemeObj.type_name) + "Dic" - resultString += self.getterMethodDefinitionStringInArray(baseSubTypeSchemeObj.getClassName() + " *", baseSubTypeSchemeObj.type_name, titleName, postFix) - resultString += self.getDictionaryGetterFromArrayCode(tmpDicName, selfDicName, "index", (schemeObj.required != True), 1, "nil") - resultString += " " + baseSubTypeSchemeObj.getClassName() + " *" + tmpVarName + " = nil;\n" - resultString += self.getHandleErrorCode( tmpDicName +" == nil", "", "nil", 1) - resultString += self.getObjectAllocatorFromDictionaryCode(False, baseSubTypeSchemeObj.getClassName(), tmpVarName, tmpDicName, (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - - else : - resultString += self.getterMethodDefinitionStringInArray(self.getNaturalTypeClassString(baseSubTypeSchemeObj.rootBaseType()), baseSubTypeSchemeObj.type_name,titleName,postFix) - resultString += self.getNaturalTypeGetterFromArrayCode(baseSubTypeSchemeObj, self.getNaturalTypeClassString(baseSubTypeSchemeObj.rootBaseType()), tmpVarName, selfDicName, "index", (schemeObj.required != True), 1, "nil") - resultString += self.getNaturalTypeValidationCode(baseSubTypeSchemeObj, tmpVarName, 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - - - elif schemeName == "any" : - resultString += self.getterMethodDefinitionStringInArray("id", "object", titleName, postFix) - resultString += self.getGetterFromArrayCode("id ", tmpVarName, selfDicName, "index", (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - else : - resultString += self.getterMethodDefinitionStringInArray(self.getNaturalTypeClassString(schemeName), schemeName, titleName, postFix) - resultString += self.getNaturalTypeGetterFromArrayCode(schemeName, self.getNaturalTypeClassString(schemeName), tmpVarName, selfDicName, "index", (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - - elif schemeObj.base_type == "any" : - resultString += self.getterMethodDefinitionStringInDictionary("id", schemeObj.type_name, "Object", postFix) - resultString += self.getUndefinedTypeGetterFromDictionaryCode("id ", tmpVarName, selfDicName, schemeObj.type_name, (schemeObj.required != True), 1, "nil") - resultString += " return " + tmpVarName + ";\n}\n" - - elif schemeObj.isNaturalType() : - print "Error : " + schemeObj.type_name + " is Natural type. don't need to implement getter method.\n" - return "#error " + schemeObj.type_name + " is Natural type. don't need to implement getter method.\n" - - else : - print "Error : " + schemeObj.type_name + " is Custom Object type. don't need to implement getter method.\n" - return "#error " + schemeObj.type_name + " is Custom Object type. don't need to implement getter method.\n" - - return resultString - - def getIndentString(self, indentDepth) : - resultString = "" - indentString = " " - for loop in range(indentDepth) : - resultString += indentString - - return resultString - - def getHandleErrorCode(self, statement, errorString, returnVarName, indentDepth) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - resultString += firstIndent + "if ("+ statement + ") {\n" - if len(errorString) : - resultString += secondIndent + errorString - resultString += secondIndent + "return " + returnVarName + ";\n" + firstIndent + "}\n" - return resultString - - def getStringValidationCode(self, schemeObj, varName, indentDepth, returnVarName) : - resultString = "" - statementString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - errorString = "NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:@\"" + self.makeVarName(schemeObj) + "\", @\"propertyName\", @\"" + schemeObj.type_name + "\", @\"key\", @\"validation error\", @\"reason\", NSStringFromClass([self class]), @\"objectClass\",nil];\n" - errorString += secondIndent + "*error = [NSError errorWithDomain:k" + self.projectPrefix + "ErrorDomain_parser code:k" + self.projectPrefix + "ErrorDomain_parser_valueIsNotValid userInfo:userInfo];\n" - errorString += secondIndent + "NSLog(@\"%@\", *error);\n" - - maxResult = schemeObj.getMaxLength() - - if maxResult[0] : - statementString = str(varName) + ".length > " + str(maxResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - minResult = schemeObj.getMinLength() - if minResult[0] : - statementString = varName + ".length < " + str(minResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - regExResult = schemeObj.getRegex() - if regExResult[0] : - statementString = varName + " && ["+varName+" matchesRegExString:@\"" +str(regExResult[1])+ "\"] == NO" - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - return resultString - - def getDateValidationCode(self, schemeObj, varName, indentDepth, returnVarName) : - resultString = "" - statementString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - errorString = "NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:@\"" + self.makeVarName(schemeObj) + "\", @\"propertyName\", @\"" + schemeObj.type_name + "\", @\"key\", @\"validation error\", @\"reason\", NSStringFromClass([self class]), @\"objectClass\",nil];\n" - errorString += secondIndent + "*error = [NSError errorWithDomain:k" + self.projectPrefix + "ErrorDomain_parser code:k" + self.projectPrefix + "ErrorDomain_parser_valueIsNotValid userInfo:userInfo];\n" - errorString += secondIndent + "NSLog(@\"%@\", *error);\n" - - maxResult = schemeObj.getMaxValue() - if maxResult[0] : - statementString = "["+varName+" timeIntervalSince1970] > " + str(maxResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - minResult = schemeObj.getMinValue() - if minResult[0] : - statementString = "["+varName+" timeIntervalSince1970] < " + str(minResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - return resultString - - def getDataValidationCode(self, schemeObj, varName, indentDepth, returnVarName) : - resultString = "" - statementString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - errorString = "NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:@\"" + self.makeVarName(schemeObj) + "\", @\"propertyName\", @\"" + schemeObj.type_name + "\", @\"key\", @\"validation error\", @\"reason\", NSStringFromClass([self class]), @\"objectClass\",nil];\n" - errorString += secondIndent + "*error = [NSError errorWithDomain:k" + self.projectPrefix + "ErrorDomain_parser code:k" + self.projectPrefix + "ErrorDomain_parser_valueIsNotValid userInfo:userInfo];\n" - errorString += secondIndent + "NSLog(@\"%@\", *error);\n" - - maxResult = schemeObj.getMaxLength() - if maxResult[0] : - statementString = varName+".length > " + str(maxResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - minResult = schemeObj.getMinLength() - if minResult[0] : - statementString = varName+".length < " + str(minResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - return resultString - - def getNumberValidationCode(self, schemeObj, varName, indentDepth, returnVarName) : - resultString = "" - statementString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - errorString = "NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:@\"" + self.makeVarName(schemeObj) + "\", @\"propertyName\", @\"" + schemeObj.type_name + "\", @\"key\", @\"validation error\", @\"reason\", NSStringFromClass([self class]), @\"objectClass\",nil];\n" - errorString += secondIndent + "*error = [NSError errorWithDomain:k" + self.projectPrefix + "ErrorDomain_parser code:k" + self.projectPrefix + "ErrorDomain_parser_valueIsNotValid userInfo:userInfo];\n" - errorString += secondIndent + "NSLog(@\"%@\", *error);\n" - - maxResult = schemeObj.getMaxValue() - if maxResult[0] : - statementString = "["+varName+" floatValue] > " + str(maxResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - minResult = schemeObj.getMinValue() - if minResult[0] : - statementString = "["+varName+" floatValue] < " + str(minResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - return resultString - - def getArrayValidationCode(self, schemeObj, varName, indentDepth, returnVarName) : - resultString = "" - statementString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - errorString = "NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:@\"" + self.makeVarName(schemeObj) + "\", @\"propertyName\", @\"" + schemeObj.type_name + "\", @\"key\", @\"validation error\", @\"reason\", NSStringFromClass([self class]), @\"objectClass\",nil];\n" - errorString += secondIndent + "*error = [NSError errorWithDomain:k" + self.projectPrefix + "ErrorDomain_parser code:k" + self.projectPrefix + "ErrorDomain_parser_valueIsNotValid userInfo:userInfo];\n" - errorString += secondIndent + "NSLog(@\"%@\", *error);\n" - - maxResult = schemeObj.getMaxCount() - if maxResult[0] : - statementString = varName+".count > " + str(maxResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - minResult = schemeObj.getMinCount() - if minResult[0] : - statementString = varName+".count < " + str(minResult[1]) - resultString += self.getHandleErrorCode(statementString, errorString, returnVarName, indentDepth) - - return resultString - - def getNaturalTypeValidationCode(self, schemeObj, varName, indentDepth, returnVarName) : - if schemeObj.isNaturalType() : - if schemeObj.rootBaseType() == "array" : - return self.getArrayValidationCode(schemeObj, varName, indentDepth, returnVarName) - elif schemeObj.rootBaseType() == "string" : - return self.getStringValidationCode(schemeObj, varName, indentDepth, returnVarName) - elif schemeObj.rootBaseType() == "number" : - return self.getNumberValidationCode(schemeObj, varName, indentDepth, returnVarName) - elif schemeObj.rootBaseType() == "date" : - return self.getDateValidationCode(schemeObj, varName, indentDepth, returnVarName) - elif schemeObj.rootBaseType() == "data" : - return self.getDataValidationCode(schemeObj, varName, indentDepth, returnVarName) - - return "" - - - def getNaturalTypeGetterFromDictionaryCode(self, schemeObj, className, varName, dicName, keyName, allowNull, indentDepth, returnVarName) : - schemeBaseType = "" - if type(schemeObj) == str or type(schemeObj) == unicode: - schemeBaseType = str(schemeObj) - elif schemeObj.isNaturalType() : - schemeBaseType = str(schemeObj.rootBaseType()) - else : - print "Error (getNaturalTypeGetterFromDictionaryCode): undfined scheme base type " + schemeObj - return "#error - undfined scheme base type\n" - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - if schemeBaseType == "array" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser arrayFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - elif schemeBaseType == "string" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser stringFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNumber:NO acceptNil:" - elif schemeBaseType == "number" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser numberFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - elif schemeBaseType == "date" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser dateWithTimeIntervalFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - elif schemeBaseType == "data" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser dataFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - elif schemeBaseType == "boolean" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser boolFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - else : - print "Error (getNaturalTypeGetterFromDictionaryCode): undfined scheme natural base type " + schemeObj - return "#error - undfined scheme natural base type\n" - - if allowNull : - resultString += "YES" - else : - resultString += "NO" - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - - return resultString - - def getUndefinedTypeGetterFromDictionaryCode(self, className, varName, dicName, keyName, allowNull, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - resultString += firstIndent - if className and len(className) : - resultString += className - resultString += varName + " = [" + self.projectPrefix + "APIParser objectFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - - if allowNull : - resultString += "YES" - else : - resultString += "NO" - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - - return resultString - - def getNaturalTypeGetterFromArrayCode(self, schemeObj, className, varName, arrayName, indexVar, allowNull, indentDepth, returnVarName) : - schemeBaseType = "" - if type(schemeObj) == str or type(schemeObj) == unicode: - schemeBaseType = str(schemeObj) - elif schemeObj.isNaturalType() : - schemeBaseType = str(schemeObj.rootBaseType()) - else : - print "Error (getNaturalTypeGetterFromArrayCode): undfined scheme base type " + schemeObj - return "#error - undfined scheme base type\n" - - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - if schemeBaseType == "array" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser arrayFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - elif schemeBaseType == "string" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser stringFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - elif schemeBaseType == "number" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser numberFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - elif schemeBaseType == "date" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser dateWithTimeIntervalFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - elif schemeBaseType == "data" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser dataFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - elif schemeBaseType == "boolean" : - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser boolFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - else : - print "Error (getNaturalTypeGetterFromArrayCode): undfined scheme natural base type " + schemeObj - return "#error - undfined scheme natural base type\n" - - if allowNull : - resultString += "YES" - else : - resultString += "NO" - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - - return resultString - - def getDictionaryGetterFromDictionaryCode(self, varName, dicName, keyName, allowNull, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - resultString += firstIndent + "NSDictionary *"+ varName + " = [" + self.projectPrefix + "APIParser dictionaryFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - if allowNull : - resultString += "YES" - else : - resultString += "NO" - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - return resultString - - def getDictionaryGetterFromArrayCode(self, varName, arrayName, indexVar, allowNull, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - resultString += firstIndent + "NSDictionary *"+ varName + " = [" + self.projectPrefix + "APIParser dictionaryFromResponseArray:" + arrayName + " atIndex:" + indexVar + " acceptNil:" - if allowNull : - resultString += "YES" - else : - resultString += "NO" - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - - return resultString - - def getObjectAllocatorFromDictionaryCode(self, defineClass, className, varName, dicName, allowNull, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - resultString += firstIndent + "if (" + dicName + ") {\n" - resultString += secondIndent - if defineClass : - resultString += className+ " *" - resultString += varName + "= [[" + className + " alloc] initWithDictionary:" + dicName + " withError:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth + 1) - resultString += firstIndent + "}\n" - - return resultString - - def getDictionaryAllocatorCode(self, defineClass, varName, objectName, keyNmae, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - resultString += firstIndent - if defineClass : - resultString += "NSDictionary *" - resultString += varName + " = [NSDictionary dictionaryWithObjectsAndKeys:"+ objectName +", @\"" + keyNmae + "\", nil];\n" - - return resultString - - def getGetterFromDictionaryCode(self, className, varName, dicName, keyName, allowNull, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser objectFromResponseDictionary:" + dicName + " forKey:@\"" + keyName + "\" acceptNil:" - if allowNull : - resultString += "YES" - else : - resultString += "NO" - - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - return resultString - - def getGetterFromArrayCode(self, className, varName, arrayName, indexVar, allowNull, indentDepth, returnVarName) : - resultString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth+1) - resultString += firstIndent + className + varName + " = [" + self.projectPrefix + "APIParser objectFromResponseArray:" + arrayName + " atIndex:" + indexVar - resultString += " acceptNil:" - if allowNull : - resultString += "YES" - else : - resultString += "NO" - resultString += " error:error];\n" - resultString += self.getHandleErrorCode("*error", "", returnVarName, indentDepth) - return resultString - - def propertyDefinitionString(self, schemeObj) : - resultString = "" - - if schemeObj.isNaturalType() : - if schemeObj.rootBaseType() == "boolean" : - return "@property (nonatomic, assign) BOOL " + self.makeVarName(schemeObj) + ";\n" - elif schemeObj.rootBaseType() == "string" : - return "@property (nonatomic, strong) NSString *" + self.makeVarName(schemeObj) + ";\n" - elif schemeObj.rootBaseType() == "date" : - return "@property (nonatomic, strong) NSDate *" + self.makeVarName(schemeObj) + ";\n" - elif schemeObj.rootBaseType() == "data" : - return "@property (nonatomic, strong) NSData *" + self.makeVarName(schemeObj) + ";\n" - elif schemeObj.rootBaseType() == "number" : - return "@property (nonatomic, strong) NSNumber *" + self.makeVarName(schemeObj) + ";\n" - elif schemeObj.rootBaseType() == "array" : - return "@property (nonatomic, strong) NSArray *" + self.makeVarName(schemeObj) + ";\n" - else : - return "@property (nonatomic, strong) id " + self.makeVarName(schemeObj) + ";\n" - - elif schemeObj.rootBaseType() == "multi" or schemeObj.rootBaseType() == "any" : - return "@property (nonatomic, strong) NSDictionary *" + self.makeVarName(schemeObj) + ";\n" - - - return "@property (nonatomic, strong) "+ schemeObj.getClassName() +" *" + self.makeVarName(schemeObj) + ";\n" - - def propertyDecodeString(self, schemeObj, indentDepth) : - firstIndent = self.getIndentString(indentDepth) - if schemeObj.isNaturalType() and schemeObj.rootBaseType() == "boolean" : - return firstIndent + "self." + self.makeVarName(schemeObj) + " = [coder decodeBoolForKey:@\"" + schemeObj.type_name + "\"];\n" - - return firstIndent + "self." + self.makeVarName(schemeObj) + " = [coder decodeObjectForKey:@\"" + schemeObj.type_name + "\"];\n" - - def propertyEncodeString(self, schemeObj, indentDepth) : - firstIndent = self.getIndentString(indentDepth) - if schemeObj.isNaturalType() and schemeObj.rootBaseType() == "boolean" : - return firstIndent + "[coder encodeBool:self." + self.makeVarName(schemeObj)+ " forKey:@\"" + schemeObj.type_name+"\"];\n" - - return firstIndent + "[coder encodeObject:self." + self.makeVarName(schemeObj)+ " forKey:@\"" + schemeObj.type_name+"\"];\n" - - def setPropertyDictionaryString(self, schemeObj, dicName, indentDepth) : - returnString = "" - firstIndent = self.getIndentString(indentDepth) - secondIndent = self.getIndentString(indentDepth + 1) - thirdIndent = self.getIndentString(indentDepth + 2) - returnString += firstIndent + "if (self." + self.makeVarName(schemeObj) + ") {\n" - if schemeObj.isNaturalType() : - if schemeObj.rootBaseType() == "boolean" : - returnString += secondIndent + "[" + dicName+ " setObject:[NSNumber numberWithBool:self." + self.makeVarName(schemeObj) + "] forKey:@\"" + schemeObj.type_name + "\"];\n" - elif schemeObj.rootBaseType() == "date" : - returnString += secondIndent + "[" + dicName+ " setObject:[NSNumber numberWithInteger:[[NSNumber numberWithDouble:[self." + self.makeVarName(schemeObj) + " timeIntervalSince1970]] longValue]] forKey:@\"" + schemeObj.type_name + "\"];\n"; - elif schemeObj.rootBaseType() == "array" : - arrayObjType = schemeObj.getSubType() - if arrayObjType and len(arrayObjType) == 1 and schemeObj.hasScheme(arrayObjType[0]) == True : - arraySchemeObj = schemeObj.getScheme(arrayObjType[0]) - returnString += secondIndent + "NSMutableArray *tmpArray = [[NSMutableArray alloc] init];\n" - if arraySchemeObj.rootBaseType() == "object" : - returnString += secondIndent + "for (" + arraySchemeObj.getClassName() + " *tmpObj in self." + self.makeVarName(schemeObj) + ") {\n" - returnString += thirdIndent + "[tmpArray addObject:[tmpObj propertyDictionary]];\n" - else : - returnString += secondIndent + "for (id tmpObj in self." + self.makeVarName(schemeObj) + ") {\n" - returnString += thirdIndent + "[tmpArray addObject:tmpObj];\n" - - returnString += secondIndent + "}\n" - returnString += secondIndent + "[" + dicName + " setObject:tmpArray forKey:@\"" + schemeObj.type_name + "\"];\n" - else : - returnString += secondIndent + "[" + dicName + " setObject:self." + self.makeVarName(schemeObj) + " forKey:@\"" + schemeObj.type_name + "\"];\n" - else : - returnString += secondIndent + "[" + dicName + " setObject:self." + self.makeVarName(schemeObj) + " forKey:@\"" + schemeObj.type_name + "\"];\n" - elif schemeObj.rootBaseType() == "multi" or schemeObj.rootBaseType() == "any" : - returnString += secondIndent + "[" + dicName + " setObject:self." + self.makeVarName(schemeObj) + " forKey:@\"" + schemeObj.type_name + "\"];\n" - else : - returnString += secondIndent + "[" + dicName + " setObject:[self." + self.makeVarName(schemeObj) + " propertyDictionary] forKey:@\"" + schemeObj.type_name + "\"];\n" - - returnString += firstIndent + "}\n" - return returnString - - -class TemplateCodeGenerator : - - projectPrefix = "" - dirPath = "" - templatePath = "./templates" - - def __init__(self): - projectPrefix = "S2M" - dirPath = "classes" - templatePath = "./templates" - def writeNSStringCategory(self) : - today = datetime.date.fromtimestamp(time.time()) - if not os.path.exists(self.dirPath): - os.makedirs(self.dirPath) - - headerDstFile = open(self.dirPath + "/NSString+RegExValidation.h", "w") - headerSrcFile = self.templatePath + "/NSString+RegExValidation.h" - - try: - for line in open(headerSrcFile): - newLine = line.replace('_DATE_', "") - newLine = newLine.replace('_YEAR_', str(today.year)) - headerDstFile.write(newLine) - finally : - headerDstFile.close() - - implDstFile = open(self.dirPath + "/NSString+RegExValidation.m", "w") - implSrcFile = self.templatePath + "/NSString+RegExValidation.m" - - try: - for line in open(implSrcFile): - newLine = line.replace('_DATE_', "") - newLine = newLine.replace('_YEAR_', str(today.year)) - implDstFile.write(newLine) - finally : - implDstFile.close() - - def writeAPIParser(self) : - today = datetime.date.fromtimestamp(time.time()) - if not os.path.exists(self.dirPath): - os.makedirs(self.dirPath) - - headerDstFile = open(self.dirPath + "/"+self.projectPrefix+"APIParser.h", "w") - headerSrcFile = self.templatePath + "/APIParser/APIParser.h" - - - try: - for line in open(headerSrcFile): - newLine = line.replace('_DATE_', "") - newLine = newLine.replace('_YEAR_', str(today.year)) - newLine = newLine.replace('_PREFIX_', self.projectPrefix) - headerDstFile.write(newLine) - finally : - headerDstFile.close() - - implDstFile = open(self.dirPath + "/"+self.projectPrefix+"APIParser.m", "w") - implSrcFile = self.templatePath + "/APIParser/APIParser.m" - - try: - for line in open(implSrcFile): - newLine = line.replace('_DATE_', "") - newLine = newLine.replace('_YEAR_', str(today.year)) - newLine = newLine.replace('_PREFIX_', self.projectPrefix) - implDstFile.write(newLine) - finally : - implDstFile.close() - - def writeTemplates(self) : - - if self.dirPath.endswith("/") : - self.dirPath = self.dirPath[:-1] - baseDirPath = self.dirPath - self.dirPath = baseDirPath + "/Utilities/NSString" - self.writeNSStringCategory() - self.dirPath = baseDirPath + "/Utilities/APIParser" - self.writeAPIParser() - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md index b53f43d..2cb5f10 100644 --- a/README.md +++ b/README.md @@ -4,60 +4,31 @@ metaJSON provides a meta language to generate object models for several language ## Usage -1. Write your JSON scheme according to the JSON spec of your backend (for yaml, please see details below) +1. Write your [JSON scheme](https://github.com/sinnerschrader-mobile/metaJSON/wiki/Protocol) according to the JSON spec of your backend 2. Run the script ``` -# python readJSON.py -h - -readJSON.py [ -p | -t | -o | -s ] [-i] +# metajson -h Options: + -v, --version shows version -h, --help shows help - -p, --prefix= project prefix (default: S2M) - -s, --suffix= classname suffix (default: JSONObject). Use "-s false" for no suffix - -t, --target= target platform iOS or Android (default: iOS) - -i, --input= meta-JSON file to read - -o, --output= ouput path of generated source codes + -p, --prefix= project prefix (default: S2M) + -s, --suffix= classname suffix (default: JSONObject). Use "-s false" for no suffix + -i, --input= meta-JSON file to read + -o, --output= ouput path of generated source codes (default: src) + --template= template directory to use to generate code + --package= name of the generated package (default: none) ``` A working sample call could look like that: ``` -# python readJSON.py --p GitHub -t Android -i github-scheme.json -o com/example/project/android/json +# metajson --p GitHub -i github-scheme.json -o com/example/project/android/json --template=metajson/templates/Android --package=com.example.project.android.json ``` The result of that call will be generated Java code in the folder "com". The java package structure and definition will be there, so you just need to copy the folder in your project structure. It is ready to be used. - - ## Documentation -See MetaJSONProtocol.md file in the doc folder. - -## Known issues -Please check the issue tracker and/or refer to the known_issues.md file in the doc folder. +See [Wiki](https://github.com/sinnerschrader-mobile/metaJSON/wiki) ## License -The project is published with the MIT License. Please read the LICENSE.txt for more details. \ No newline at end of file +The project is published with the MIT License. Please read the LICENSE.txt for more details. diff --git a/doc/MetaJSONProtocol.md b/doc/MetaJSONProtocol.md deleted file mode 100644 index 8e87c5f..0000000 --- a/doc/MetaJSONProtocol.md +++ /dev/null @@ -1,617 +0,0 @@ -# Writing Meta JSON and Using Meta JSON - -##1. define a type (common) - -``` -{ -"name" : string, -"base-type" : string or array, -"description" : string, -} -``` -* "name" and "base-type" are mandatory meta-data for all types. -* "description" is optional to understand what this property means. -* the value of "base-type" should be "boolean", "number", "string", "data", "date", "array", "object", "any" or a name of custom base-type. - -##2. define string type - -``` -{ -"name" : "myString", -"base-type" : "string", -"description" : string, -"regex" : regular expression string, -"maxLength" : positive integer or zero, -"minLength" : positive integer or zero -} -``` - -* "regex", "maxLength" and "minLength" are optional, to validate this type. -* "maxLength" should be always same or bigger than "minLength". - -You can also use just one of those ("minLength" or "maxLength"). - - -##3. define number type - -``` -{ - "name" : "myNumber", - "base-type" : "number", - "description" : string, - "maxValue" : real number, - "minValue" : real number -} -``` - -* "minValue" and "maxValue" are optional, to validate this type. -* "maxValue" should be always same or bigger than "minValue". - -You can also use just one of those ("minValue" or "maxValue"). - - -##4. define date type - -``` -{ - "name" : "myDate", - "base-type" : "date", - "description" : string - "minValue" : UTC time interval since 1970 - "maxValue" : UTC time interval since 1970 -} -``` - -* The value of myDate should be always UTC time interval since 1970. -* "minValue" and "maxValue" are optional, to validate this type. -* "maxValue" should be always same or later than "minValue". - -You can also use just one of those ("minValue" or "maxValue"). - - -##5. define boolean type - -``` -{ - "name" : "myBoolean", - "base-type" : "boolean", - "description" : string -} -``` - -##6. define data type - -``` -{ - "name" : "myData", - "base-type" : "data", - "description" : string, - "maxLength" : positive integer or zero, - "minLength" : positive integer or zero -} -``` - -* "maxLength" and "minLength" are optional, to validate this type. -* "maxLength" should be always same or bigger than "minLength". - - -##7. define array type - -``` -{ - "name" : "myArray", - "base-type" : "array", - "description" : string, - "subType" : string, - "maxCount" : positive integer or zero, - "minCount" : positive integer or zero -} -``` - -* "maxCount" and "minCount" are optional, to validate this type. -* "maxCount" should be always same or bigger than "minCount". -* "subType" should be boolean, number, string, data, date, array, object and any or a name of custom base-type. - - -##8. define custom type - -``` -{ - "name" : "myCustom", - "base-type" : "object", - "description" : "description-value", - "property" : [ - { - "name" : "property1" - "base-type" : "string", - "required" : "boolean", - }, - { - "name" : "property2" - "base-type" : "number", - "required" : "boolean", - }, - . - . - . - ] -} -``` - -To define custom type, you should write "property" (mandatory). -Property can have many different kind of types (boolean, number, string, data, date, array, object, any and/or custom object) -but "property" must have 1 or more types. - - -##9. define child type from custom type - -``` -{ - "name" : "myChild", - "base-type" : "myCustom", - "description" : string, - "property" : [ - { - "name" : "property3" - "base-type" : "myString", - "required" : boolean, - }, - . - . - . - ] -} -``` - -If you want to define child type from other custom type, you just need to write parent type's name in "base-type" field. -And you can also define other additional properties, or override existing properties. -In this case, "property" is not mandatory. - - -##10. define multi-type - -``` -{ - "name" : "myMultiType", - "base-type" : ["string", "number", "typeA", …], - "required" : boolean, - "description" : string -} -``` - -And when the base-type is json-array type, code generator has to implement method which is looked like - -``` - (JSONObject *)myMultiType; - (JSONString *)myMultiTypeAsString; - (JSONNumber *)myMultiTypeAsNumber; - (TypeA *)myMultiTypeAsTypeA; - . - . - . -``` - -And if subType is "any", the code generator will make just a method which will return the original JSON subtree (ex : Objective-c method can return any basic JSON type). - -``` - (JSONObject *) myMultiType; -``` - -##11. define multi-type array type - -``` -{ - "name" : "mtArray", - "base-type" : "array", - "description" : string, - "sub-type" : ["string", "number", "typeB", …], -} -``` - -Code generator has to implement method which is looked like - -``` - (JSONObject *)mtArrayObjectIndexAt:(NSUInteger)index; - (JSONString *)mtArrayObjectAsStringIndexAt:(NSUInteger)index; - (JSONNumber *)myArrayObjectAsNumberIndexAt:(NSUInteger)index; - (TypeB *)mtArrayObjectAsTypeBIndexAt:(NSUInteger)index; - . - . - . -``` - -And if subType is "any", the code generator will make just a method which will return the original JSON subtree (ex : Objective-c method can return any basic JSON type). - -``` - (JSONObject *)mtArrayObjectIndexAt:(NSUInteger)index; -``` - - -##12. several ways to define type and use - -Top-level Meta-JSON is an array where each element is one of "string", "array", "number", "boolean", ..., "object" and child type of custom type. - -###12.1. basic definition and usage - -``` -[ - { - "name" : "sessionString", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20 - }, - { - "name" : "sessionExpirationDate", - "base-type" : "date", - "description" : "Expire date of session", - "maxValue" : 183759284 - }, - { - "name" : "mySession", - "base-type" : "object", - "description" : "session has session id and session expire date.", - "property" : - [ - { - "name" : "sessionID", - "base-type" : "sessionString", - "required" : 1 - }, - { - "name" : "expirationDate", - "base-type" : "sessionExpirationDate", - "required" : 1 - } - ] - }, - { - "name" : "user", - "base-type" : "object", - "description" : "test description of user type.", - "property" : - [ - { - "name" : "session", - "base-type" : "mySession", - "required" : 1 - }, - { - "name" : "userName", - "base-type" : "string", - "required" : 1 - } - ] - } -] -``` - -###12.2. define type in "base-type" -* the type named "person" is always accessible and reusable in other types. -* in this case, "user" type is a child type from "person" type. - -``` -[ - { - "name" : "sessionString", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20 - }, - { - "name" : "sessionExpirationDate", - "base-type" : "date", - "description" : "Expire date of session", - "maxValue" : 183759284 - }, - { - "name" : "mySession", - "base-type" : "object", - "description" : "session has session id and session expire date.", - "property" : - [ - { - "name" : "sessionID", - "base-type" : "sessionString", - "required" : 1 - }, - { - "name" : "expirationDate", - "base-type" : "sessionExpirationDate", - "required" : 1 - } - ] - }, - { - "name" : "user", - "base-type" : - { - "name" : "person", - "base-type" : "object", - "description" : ".", - "property" : - [ - { - "name" : "email", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "birthday", - "base-type" : "date", - "required" : 1 - } - ] - }, - "description" : "test description of user type.", - "property" : - [ - { - "name" : "userName", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "userSession", - "base-type" : "mySession", - "required" : 1 - } - ] - } -] -``` - -###12.3. define type in "property" - -``` -[ - { - "name" : "sessionString", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20, - }, - { - "name" : "sessionExpirationDate", - "base-type" : "date", - "description" : "Expire date of session" - "maxValue" : 183759284 - }, - { - "name" : "user", - "base-type" : "object", - "description" : "test description of user type.", - "property" : - [ - { - "name" : "session" - "base-type" : { - "name" : "mySession", - "base-type" : "object", - "description" : "session has session id and session expire date.", - "property" : - [ - { - "name" : "sessionID" - "base-type" : "sessionString", - "required" : 1, - }, - { - "name" : "expirationDate" - "base-type" : "sessionExpirationDate", - "required" : 1, - } - ] - }, - "required" : 1, - }, - { - "name" : "userName" - "base-type" : "string", - "required" : 1, - } - ] - } -] -``` - -###12.4. define type in "subType" of array -* "userSession" property can have "sessionID" type and "expirationDate". -* (it's not a good example……) - -``` -[ - { - "name" : "sessionString", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20, - }, - { - "name" : "sessionExpirationDate", - "base-type" : "date", - "description" : "Expire date of session" - "maxValue" : 183759284 - }, - { - "name" : "mySession", - "base-type" : "array", - "description" : "session has session-ids and session expire dates.", - "subType" : - [ - { - "name" : "sessionID" - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20, - }, - { - "name" : "expirationDate", - "base-type" : "date", - "description" : "Expire date of session" - "maxValue" : 183759284 - } - ] - }, - { - "name" : "user", - "base-type" : "object", - "description" : "test description of user type.", - "property" : - [ - { - "name" : "userName" - "base-type" : "string", - "required" : 1, - }, - { - "name" : "userSession" - "base-type" : "mySession", - "required" : 1, - } - ] - } -] -``` - -###12.5. override the value of predefined keys in predefine type. -* I just overrides the maxLength value of "sessionString". - -``` -[ - { - "name" : "sessionString", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20, - }, - { - "name" : "mySession", - "base-type" : "object", - "description" : "session has session id and session expire date.", - "property" : - [ - { - "name" : "sessionID", - "base-type" : "sessionString", - "description" : "session string after login", - "maxLength" : 30, - }, - { - "name" : "expirationDate" - "base-type" : "sessionExpirationDate", - "required" : 1, - } - ] - }, - { - "name" : "user", - "base-type" : "object", - "description" : "test description of user type.", - "property" : - [ - { - "name" : "session" - "base-type" : "mySession", - "required" : 1, - }, - { - "name" : "userName" - "base-type" : "string", - "required" : 1, - } - ] - } -] -``` - -###12.6. override the properties of predefined types. -- user type is a child type of person. -- redefine the property named "email" with new "regex" key. - -``` -[ - { - "name" : "sessionString", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20, - }, - { - "name" : "sessionExpirationDate", - "base-type" : "date", - "description" : "Expire date of session" - "maxValue" : 183759284 - }, - { - "name" : "mySession", - "base-type" : "object", - "description" : "session has session id and session expire date.", - "property" : - [ - { - "name" : "sessionID" - "base-type" : "sessionString", - "required" : 1, - }, - { - "name" : "expirationDate" - "base-type" : "sessionExpirationDate", - "required" : 1, - } - ] - }, - { - "name" : "person", - "base-type" : "object", - "description" : ".", - "property" : - [ - { - "name" : "email" - "base-type" : "string", - "required" : 1, - }, - { - "name" : "birthday" - "base-type" : "date", - "required" : 1, - } - ] - }, - { - "name" : "user", - "base-type" : "person" - "description" : "test description of user type.", - "property" : - [ - { - "name" : "email" - "base-type" : "string", - "regex" : "[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}" - "required" : 1, - }, - - { - "name" : "session" - "base-type" : "mySession", - "required" : 1, - }, - { - "name" : "userName" - "base-type" : "string", - "required" : 1, - } - ] - } -] -``` - - diff --git a/doc/known_issues.md b/doc/known_issues.md deleted file mode 100644 index 1d18265..0000000 --- a/doc/known_issues.md +++ /dev/null @@ -1,22 +0,0 @@ -#Currently known issues - -###Predefined primitive type - -A definition like below which might be referenced as sub or base type is not yet supported by the java code generator. Using that will result in valid Objective-C code but will lead to invalid code for Java. It can be used but manual "reparation" of the generated code is required. - -``` -{ - "name" : "titleString", - "base-type" : "string", - "description" : "the title of product", - "minLength" : 10, - "maxLength" : 20, - "regex" : "[a-z0-9]:10", - "required" : 1 -} -``` - -###Documentation Topic 12 -The complete topic 12 is not yet fully supported and/or tested. Some parts might already work but there is no intentionally support implemented yet. - -We highly appreciate any contribution to this work-in-progress project. \ No newline at end of file diff --git a/metajson-runner.py b/metajson-runner.py new file mode 100755 index 0000000..6124665 --- /dev/null +++ b/metajson-runner.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""Convenience wrapper for running metajson directly from source tree.""" + + + +import sys + +if __name__ == '__main__': + from metajson.readJSON import main + sys.exit(main(sys.argv)) diff --git a/JSONScheme.py b/metajson/JSONScheme.py similarity index 94% rename from JSONScheme.py rename to metajson/JSONScheme.py index e6eda3c..6a0104f 100755 --- a/JSONScheme.py +++ b/metajson/JSONScheme.py @@ -26,6 +26,7 @@ class JSONScheme : JSONSchemeDic = {} naturalTypeList = ['string', 'array', 'date', 'data', 'boolean', 'number'] projectPrefix = "" + packageName = "" objectSuffix = "JSONObject" type_name = "" key_name = "" @@ -42,19 +43,17 @@ class JSONScheme : hasMaxLength = False hasMinLength = False required = False - + maxCount = 0 minCount = 0 maxValue = 0 minValue = 0 maxLength = 0 minLength = 0 - + domain = ["ROOT"] def __init__(self): - projectPrefix = "" - objectSuffix = "JSONObject" type_name = "" key_name = "" base_type = "" @@ -77,17 +76,20 @@ def __init__(self): maxLength = 0 minLength = 0 domain = ["ROOT"] - + + def __setattr__(self, name, value): + self.__dict__[name] = value + def hasScheme(self, schemeName) : tmpDomainList = list(self.domain) tmpDomainList.append(self.type_name) #print "find : " + schemeName + ", at : " + str(tmpDomainList) - + for nn in range(0,len(tmpDomainList)) : tmpDomainKey = "" for mm in range(0,len(tmpDomainList) - nn) : tmpDomainKey += str(tmpDomainList[mm]) - + if JSONScheme.JSONSchemeDic.has_key(tmpDomainKey) : tmpDomainDic = JSONScheme.JSONSchemeDic[tmpDomainKey] if tmpDomainDic.has_key(schemeName) : @@ -106,7 +108,7 @@ def getScheme(self, schemeName) : tmpDomainKey = "" for mm in range(0,len(tmpDomainList) - nn) : tmpDomainKey += str(tmpDomainList[mm]) - + if JSONScheme.JSONSchemeDic.has_key(tmpDomainKey) : tmpDomainDic = JSONScheme.JSONSchemeDic[tmpDomainKey] if tmpDomainDic.has_key(schemeName) : @@ -114,16 +116,16 @@ def getScheme(self, schemeName) : return False - + def getDomainString(self) : domainString = "" for index in range(0, len(self.domain)) : domainString += self.domain[index] if index in range(0,len(self.domain) - 1) : domainString += "." - + return domainString - + def getDomain(self) : domainString = "" for index in range(0, len(self.domain)) : @@ -133,114 +135,114 @@ def getDomain(self) : def setMaxValue(self, maxVal): self.maxValue = maxVal self.hasMaxValue = True - + def setMinValue(self, minVal): self.minValue = minVal self.hasMinValue = True - + def setMaxLength(self, maxLen): self.maxLength = maxLen self.hasMaxLength = True - + def setMinLength(self, minLen): self.minLength = minLen self.hasMinLength = True - + def setMaxCount(self, maxCnt): self.maxCount = maxCnt self.hasMaxCount = True - + def setMinCount(self, minCnt): self.minCount = minCnt self.hasMinCount = True - + def getMaxValue(self) : if self.hasMaxValue : return [True, self.maxValue] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) - + return parentSchemeObj.getMaxValue() - + def getMinValue(self) : if self.hasMinValue : return [True, self.minValue] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) - + return parentSchemeObj.getMinValue() - + def getMaxCount(self) : if self.hasMaxCount : return [True, self.maxCount] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) - + return parentSchemeObj.getMaxCount() - + def getMinCount(self) : if self.hasMinCount : return [True, self.minCount] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) - + return parentSchemeObj.getMinCount() - + def getMaxLength(self) : if self.hasMaxLength : return [True, self.maxLength] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) - + return parentSchemeObj.getMaxLength() - + def getMinLength(self) : if self.hasMinLength : return [True, self.minLength] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) - + return parentSchemeObj.getMinLength() - + def getRegex(self) : if len(self.regex) > 0 : return [True, self.regex] - + if self.base_type in self.naturalTypeList : return [False, 0]; - + parentSchemeObj = self.getScheme(self.base_type) if parentSchemeObj : return parentSchemeObj.getRegex() else : return [False, 0]; - + def getClassName(self): - + if self.rootBaseType() == "object" : - if self.props : + if self.props : className = self.type_name.upper() className = self.projectPrefix + className[:1] + self.type_name[1:] + self.objectSuffix - else : # it means, this scheme descripe just property info, not class info. + else : # it means, this scheme descripe just property info, not class info. className = self.base_type.upper() className = self.projectPrefix + className[:1] + self.base_type[1:] + self.objectSuffix return className @@ -249,15 +251,15 @@ def getClassName(self): return "" def getMachineClassName(self): - + className = self.getClassName() if len(className) : - machineClassName = "_" + className + machineClassName = "_" + className return machineClassName print "error : " + self.type_name + " has no Class Name." return "" - + def rootBaseType(self) : if self.base_type in JSONScheme.naturalTypeList or self.base_type == "object" or self.base_type == "multi" or self.base_type == "any": return self.base_type @@ -265,24 +267,24 @@ def rootBaseType(self) : if self.hasScheme(self.base_type) : parentTypeScheme = self.getScheme(self.base_type) return parentTypeScheme.rootBaseType() - + return self.base_type def isNaturalType(self) : - + root = self.rootBaseType() - + if root in JSONScheme.naturalTypeList : return True - + return False - + def canHaveProperty(self) : if self.rootBaseType() == "object" : return True return False - + def getSubType(self) : if self.isNaturalType() : return self.sub_type @@ -295,12 +297,12 @@ def getSubType(self) : return parentTypeScheme.getSubType() return self.sub_type - + def getBaseTypes(self) : - + if self.isNaturalType() : return self.base_type_list - + if len(self.base_type_list) : return self.base_type_list @@ -313,10 +315,11 @@ def getBaseTypes(self) : """ make new Scheme Object """ - + def makeNewScheme(self, jsonDic): newScheme = JSONScheme() newScheme.projectPrefix = self.projectPrefix + newScheme.packageName = self.packageName newScheme.objectSuffix = self.objectSuffix newScheme.domain = self.domain[:] newScheme.domain.append(self.type_name) @@ -346,10 +349,10 @@ def parseBaseType(self, jsonObj) : elif type(jsonObj) == list : self.base_type = "multi" - for multiType in jsonObj : + for multiType in jsonObj : if type(multiType) == dict : newScheme = self.makeNewScheme(multiType) - + if newScheme : tmpList.append(newScheme.type_name) else : @@ -365,16 +368,16 @@ def parseBaseType(self, jsonObj) : self.base_type = any tmpList = [] return tmpList - + tmpList.append(multiType) - - + + elif type(jsonObj) == str or type(jsonObj) == unicode: self.base_type = str(jsonObj) - + return tmpList - + """ read sub type """ @@ -382,7 +385,7 @@ def parseSubType(self, jsonObj) : tmpList = [] if type(jsonObj) == dict : newScheme = self.makeNewScheme(jsonObj) - + if newScheme : tmpList.append(newScheme.type_name) else : @@ -393,7 +396,7 @@ def parseSubType(self, jsonObj) : for multiType in jsonObj : if type(multiType) == dict : newScheme = self.makeNewScheme(multiType) - + if newScheme : if newScheme.type_name in tmpList : print "warning - ignore same type ("+ newScheme.type_name +") in subTypes of ", self.type_name @@ -411,8 +414,8 @@ def parseSubType(self, jsonObj) : return tmpList tmpList.append(str(multiType)) - - + + else : if str(jsonObj) == "any" : tmpList = ["any"] @@ -460,7 +463,7 @@ def parseDictionary(self, jsonDic): return False tmpDomainDic[self.type_name] = self - + if jsonDic.has_key('base-type') : tmpBaseType = jsonDic['base-type'] tmpBaseTypeList = self.parseBaseType(tmpBaseType) @@ -470,37 +473,37 @@ def parseDictionary(self, jsonDic): self.base_type_list = tmpBaseTypeList else : print "error - no base-type : ", self.type_name - return False - + return False + if jsonDic.has_key('description') : self.type_description = str(jsonDic['description']) - + if jsonDic.has_key('required') : self.required = jsonDic['required'] - + if jsonDic.has_key('maxValue') : self.setMaxValue(jsonDic['maxValue']) - + if jsonDic.has_key('minValue') : self.setMinValue(jsonDic['minValue']) - + if jsonDic.has_key('maxCount') : self.setMaxCount(jsonDic['maxCount']) - + if jsonDic.has_key('minCount') : self.setMinCount(jsonDic['minCount']) - + if jsonDic.has_key('maxLength') : self.setMaxLength(jsonDic['maxLength']) - + if jsonDic.has_key('minLength') : self.setMinLength(jsonDic['minLength']) - + if jsonDic.has_key('regex') : self.regex = str(jsonDic['regex']) tmpPropList = [] - + if jsonDic.has_key('property') : tmpPropList = self.parseProperty(jsonDic['property']) if tmpPropList == False : @@ -514,20 +517,8 @@ def parseDictionary(self, jsonDic): if tmpSubTypeList == False: return False self.sub_type = tmpSubTypeList - + if self.base_type == "array" and not jsonDic.has_key('subType') : print "warning - " + self.type_name + "(array type) has no subType. treat as any. " return True - - - - - - - - - - - - diff --git a/metajson/SourceCodeGenerator.py b/metajson/SourceCodeGenerator.py new file mode 100755 index 0000000..9c68296 --- /dev/null +++ b/metajson/SourceCodeGenerator.py @@ -0,0 +1,323 @@ +''' +The MIT License (MIT) + +Copyright (c) 2013 SinnerSchrader Mobile GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +''' + + +import sys +import re +from pystache import Renderer +from cStringIO import StringIO + +from template_code_generator import * + +class SourceCodeGenerator : + + def __init__(self): + self.mustache_renderer = Renderer() + + def lambda_uppercase(self, text): + process_text = Renderer().render(text, self.mustache_renderer.context) + return process_text.upper() + + def lambda_lowercase(self, text): + process_text = Renderer().render(text, self.mustache_renderer.context) + return process_text.lower() + + def lambda_capitalize(self, text): + process_text = Renderer().render(text, self.mustache_renderer.context) + return process_text.capitalize() + + def lambda_camelcase(self, text): + process_text = Renderer().render(text, self.mustache_renderer.context) + words = process_text.split('_') + return ''.join(word.title() if i else word for i, word in enumerate(words)) + + def lambda_upper_camelcase(self, text): + camelcased_text = self.lambda_camelcase(text) + return camelcased_text[:1].upper() + camelcased_text[1:] + + def lambda_snakecase(self, text): + return re.sub('([a-z0-9])([A-Z])', r'\1_\2', string).lower() + + def lambda_upper_snakecase(self, text): + return re.sub('([a-z0-9])([A-Z])', r'\1_\2', string).upper() + + def makeVarName(self,schemeObj) : + returnName = schemeObj.type_name + if str(schemeObj.type_name) == "id" or str(schemeObj.type_name) == "description" : + titleName = schemeObj.type_name.upper() + titleName = titleName[:1] + schemeObj.type_name[1:] + prefix = schemeObj.projectPrefix.lower() if schemeObj.projectPrefix else 'meta' + returnName = prefix + titleName + else : + prefixes = ["new", "alloc", "copy"] + for prefix in prefixes: + if schemeObj.type_name.startswith(prefix): + titleName = schemeObj.type_name.upper() + titleName = titleName[:1] + schemeObj.type_name[1:] + returnName = schemeObj.projectPrefix.lower() + titleName + + break + return returnName + + def meta_property(self, schemeObj): + meta_hash = {} + meta_hash['name'] = schemeObj.type_name + if schemeObj.base_type_list: + meta_hash['base-type'] = schemeObj.base_type_list + else: + meta_hash['base-type'] = schemeObj.base_type + meta_hash['description'] = schemeObj.type_description + meta_hash['subType'] = schemeObj.sub_type + if schemeObj.rootBaseType() == "string": + hasRegex, regex = schemeObj.getRegex() + if hasRegex: + meta_hash['regex'] = regex + + hasMax, maxLength = schemeObj.getMaxLength() + if hasMax: + meta_hash['maxLength'] = maxLength + + hasMin, minLength = schemeObj.getMinLength() + if hasMin: + meta_hash['minLength'] = minLength + + if schemeObj.rootBaseType() == "number": + hasMax, maxLength = schemeObj.getMaxValue() + if hasMax: + meta_hash['maxValue'] = maxLength + + hasMin, minLength = schemeObj.getMinValue() + if hasMin: + meta_hash['minValue'] = minLength + + if schemeObj.rootBaseType() == "array": + hasMax, maxLength = schemeObj.getMaxCount() + if hasMax: + meta_hash['maxCount'] = maxLength + + hasMin, minLength = schemeObj.getMinCount() + if hasMin: + meta_hash['minCount'] = minLength + + return meta_hash + + + def process_basetypes(self, propObj, propertyHash) : + # dealing with array property + if len(propObj.getBaseTypes()) == 1: + propertyHash['hasOneBasetype'] = True + elif len(propObj.getBaseTypes()) > 1: + propertyHash['hasMultipleBasetypes'] = True + else: + propertyHash['hasNoBasetypes'] = True + + for subtype in propObj.getBaseTypes(): + key = 'hasCustomType' + if subtype in propObj.naturalTypeList: + key = 'has'+ subtype.capitalize() + 'Type' + if key not in propertyHash: + propertyHash[key] = {"types": [{"type": subtype}]} + else: + propertyHash[key]["types"].append({"type": subtype}) + elif subtype == "any": + propertyHash['hasAnyType'] = {"type": "object"} + else: + # derivate baseType + if propObj.getScheme(subtype).base_type in propObj.naturalTypeList: + key = 'has'+ propObj.getScheme(subtype).base_type.capitalize() + 'Type' + subtype_infos = {"type": subtype} + # nothing, subtype_definition = self.process_properties(propObj.getScheme(subtype)) + subtype_definition = self.meta_property(propObj.getScheme(subtype)) + subtype_infos = {"type": subtype, "_type": subtype_definition} + if key not in propertyHash: + propertyHash[key] = {"types": [subtype_infos]} + else: + propertyHash[key]["types"].append(subtype_infos) + + else: + if key in propertyHash: + propertyHash[key]["subtypes"].append({"type": subtype, "className": propObj.getScheme(subtype).getClassName()}) + classes.append(propObj.getScheme(subtype).getClassName()) + else: + propertyHash[key] = { "subtypes": [{"type": subtype, "className": propObj.getScheme(subtype).getClassName()}]} + classes.append(propObj.getScheme(subtype).getClassName()) + + def process_subtypes(self, propObj, propertyHash) : + classes = [] + # dealing with array property + if len(propObj.getSubType()) == 1: + propertyHash['hasOneSubtype'] = True + elif len(propObj.getSubType()) > 1: + propertyHash['hasMultipleSubtypes'] = True + else: + propertyHash['hasNoSubtypes'] = True + + for subtype in propObj.getSubType(): + key = 'hasCustomType' + if subtype in propObj.naturalTypeList: + key = 'has'+ subtype.capitalize() + 'Type' + if key not in propertyHash: + propertyHash[key] = {"subtypes": [{"subtype": subtype}]} + else: + propertyHash[key]["subtypes"].append({"subtype": subtype}) + elif subtype == "any": + propertyHash['hasAnyType'] = {"subtype": "object"} + else: + # derivate baseType + if propObj.getScheme(subtype).base_type in propObj.naturalTypeList: + key = 'has'+ propObj.getScheme(subtype).base_type.capitalize() + 'Type' + subtype_infos = {"subtype": subtype} + # nothing, subtype_definition = self.process_properties(propObj.getScheme(subtype)) + subtype_definition = self.meta_property(propObj.getScheme(subtype)) + subtype_infos = {"subtype": subtype, "_subtype": subtype_definition} + if key not in propertyHash: + propertyHash[key] = {"subtypes": [subtype_infos]} + else: + propertyHash[key]["subtypes"].append(subtype_infos) + + else: + if key in propertyHash: + propertyHash[key]["subtypes"].append({"subtype": subtype, "className": propObj.getScheme(subtype).getClassName()}) + classes.append(propObj.getScheme(subtype).getClassName()) + else: + propertyHash[key] = { "subtypes": [{"subtype": subtype, "className": propObj.getScheme(subtype).getClassName()}]} + classes.append(propObj.getScheme(subtype).getClassName()) + + return classes + + def process_properties(self, propObj, undefined = False) : + propertyHash = {'name' : propObj.type_name, 'varName' : self.makeVarName(propObj)} + if propObj.type_description and len(propObj.type_description) : + propertyHash["description"] = propObj.type_description + if propObj.required == 1: + propertyHash['required'] = True + + if propObj.rootBaseType() == "object": + propertyHash['className'] = propObj.getClassName() + return [propertyHash['className']], propertyHash + + if propObj.rootBaseType() == "string": + hasRegex, regex = propObj.getRegex() + if hasRegex: + propertyHash['regex'] = regex + + hasMax, maxLength = propObj.getMaxLength() + if hasMax: + propertyHash['maxLength'] = maxLength + + hasMin, minLength = propObj.getMinLength() + if hasMin: + propertyHash['minLength'] = minLength + + if propObj.rootBaseType() == "number": + hasMax, maxLength = propObj.getMaxValue() + if hasMax: + propertyHash['maxValue'] = maxLength + + hasMin, minLength = propObj.getMinValue() + if hasMin: + propertyHash['minValue'] = minLength + + if propObj.rootBaseType() == "array": + hasMax, maxLength = propObj.getMaxCount() + if hasMax: + propertyHash['maxCount'] = maxLength + + hasMin, minLength = propObj.getMinCount() + if hasMin: + propertyHash['minCount'] = minLength + + # dealing with array property + if propObj.rootBaseType() == "multi": + self.process_basetypes(propObj, propertyHash) + + classes = self.process_subtypes(propObj, propertyHash) + return classes, propertyHash + + + def render(self, schemeObj, template_content) : + today = datetime.date.fromtimestamp(time.time()) + + numberProps = [] + stringProps = [] + booleanProps = [] + dataProps = [] + dateProps = [] + arrayProps = [] + undefineProps = [] + objectProps = [] + custom_classes = [] + for prop in schemeObj.props: + classes = [] + if prop.rootBaseType() == "object": + classes, prop_hash = self.process_properties(prop) + objectProps.append(prop_hash) + elif prop.rootBaseType() == "string": + classes, prop_hash = self.process_properties(prop) + stringProps.append(prop_hash) + elif prop.rootBaseType() == "number": + classes, prop_hash = self.process_properties(prop) + numberProps.append(prop_hash) + elif prop.rootBaseType() == "boolean": + classes, prop_hash = self.process_properties(prop) + booleanProps.append(prop_hash) + elif prop.rootBaseType() == "data": + classes, prop_hash = self.process_properties(prop) + dataProps.append(prop_hash) + elif prop.rootBaseType() == "date": + classes, prop_hash = self.process_properties(prop) + dateProps.append(prop_hash) + elif prop.rootBaseType() == "array": + classes, prop_hash = self.process_properties(prop) + arrayProps.append(prop_hash) + elif prop.rootBaseType() == "multi": + classes, prop_hash = self.process_properties(prop, True) + undefineProps.append(prop_hash) + else: + classes, prop_hash = self.process_properties(prop, True) + undefineProps.append(prop_hash) + if(len(classes) > 0): + custom_classes.extend(classes) + + hashParams = {"date": str(today.year), "suffix": schemeObj.objectSuffix, "prefix": schemeObj.projectPrefix, "package": schemeObj.packageName, "name": schemeObj.type_name, "varName": self.makeVarName(schemeObj), "stringProperties": stringProps, "numberProperties": numberProps, "booleanProperties": booleanProps, "dataProperties": dataProps, "dateProperties": dateProps, "arrayProperties": arrayProps, "undefinedProperties": undefineProps, "objectProperties": objectProps} + hashParams["custom_classes"] = [] + for classname in custom_classes: + if classname not in hashParams["custom_classes"]: + hashParams["custom_classes"].append(classname) + hashParams["_uppercase"] = self.lambda_uppercase + hashParams["_lowercase"] = self.lambda_lowercase + hashParams["_capitalize"] = self.lambda_capitalize + hashParams["_upper_camelcase"] = self.lambda_upper_camelcase + hashParams["_camelcase"] = self.lambda_camelcase + hashParams["_snakecase"] = self.lambda_snakecase + hashParams["_upper_snakecase"] = self.lambda_upper_snakecase + if schemeObj.getScheme(schemeObj.base_type): + hashParams['baseClassName'] = schemeObj.getScheme(schemeObj.base_type).getClassName() + + if schemeObj.base_type == 'object': + hashParams['baseTypeIsObject'] = True + + # render + sourceString = self.mustache_renderer.render(template_content, hashParams) + return sourceString diff --git a/metajson/__init__.py b/metajson/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/metajson/__main__.py b/metajson/__main__.py new file mode 100644 index 0000000..e37764c --- /dev/null +++ b/metajson/__main__.py @@ -0,0 +1,6 @@ + # -*- coding: utf-8 -*- + +"""metajson.__main__: executed when metajson directory is called as script.""" + +from .readJSON import main +main() diff --git a/metajson/readJSON.py b/metajson/readJSON.py new file mode 100755 index 0000000..1539ec4 --- /dev/null +++ b/metajson/readJSON.py @@ -0,0 +1,208 @@ +''' +The MIT License (MIT) + +Copyright (c) 2013 SinnerSchrader Mobile GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +''' + +__version__ = "1.0.0" + +import yaml + +import json +import os +import glob +import shutil +import sys, getopt + +from JSONScheme import * +from SourceCodeGenerator import * + +def main(argv=sys.argv): + # parse Options + template_dir = None + packageName = "" + jsonfiles = [] + inputfile = 'do you have files?' + projectPrefix = 'S2M' + dirPathToSaveCodes = './src' + objectSuffix = "JSONObject" + + argv = sys.argv[1:] + try: + opts, args = getopt.getopt(argv,"vhp:s:i:o:",["version", "help", "prefix=", "suffix=", "input=", "output=", "template=", "package="]) + except getopt.GetoptError: + usage() + sys.exit(2) + + for opt, arg in opts: + if opt in ("-h", "--help"): + usage() + sys.exit() + elif opt in ("-v", "--version"): + version() + elif opt in ("-p", "--prefix"): + projectPrefix = arg + elif opt in ("-i", "--input"): + inputfile = arg + elif opt in ("-o", "--output"): + dirPathToSaveCodes = arg + elif opt in ("-s", "--suffix"): + objectSuffix = arg + if objectSuffix == "false": + objectSuffix = "" + elif opt in ("--template"): + template_dir = arg + elif opt in ("--package"): + packageName = arg + addFiles = False + for arg in argv : + if arg.endswith(inputfile) : + jsonfiles.append(inputfile) + addFiles = True + continue + + if arg.startswith('-') and addFiles : + addFiles = False + break + + if addFiles : + jsonfiles.append(arg) + + if len(jsonfiles) == 0 : + print 'error - meta JSON file is not defined' + usage() + + if not os.path.exists(dirPathToSaveCodes): + os.makedirs(dirPathToSaveCodes) + + hasError = False + + print "\nGenerate source codes with Project Prefix \'" + projectPrefix + "\' and suffix \'" + objectSuffix + "\'" + print "Output path : \'" + dirPathToSaveCodes + "\'\n" + + # write templates + if dirPathToSaveCodes.endswith("/") : + dirPathToSaveCodes = dirPathToSaveCodes[:-1] + + if template_dir == None: + template_dir = os.path.join(TemplateCodeGenerator.DEFAULT_TEMPLATE_PATH, "iOS") + + templateCodeGen = TemplateCodeGenerator(template_dir, dirPathToSaveCodes, projectPrefix, packageName) + templateCodeGen.write_general_template_files() + + + # read JSON file + JSONScheme.projectPrefix = projectPrefix + JSONScheme.packageName = packageName + JSONScheme.objectSuffix = objectSuffix + for filePath in jsonfiles : + print "read " + filePath + " to parse ...." + jsonObj = read_file(filePath) + schemeObj = create_json_scheme(jsonObj) + + codeGen = SourceCodeGenerator() + allSchemes = JSONScheme.JSONSchemeDic + rootDic = allSchemes["ROOT"] + for typeName in rootDic : + obj = rootDic[typeName]; + if obj.isNaturalType() == False: + for template_filename in templateCodeGen.json_template_files: + template = open(template_filename) + content = codeGen.render(obj, template.read()) + file = templateCodeGen.create_template_output_file(template_filename, obj.getClassName()) + try: + file.write(content) + finally : + file.close() + + + +def create_json_scheme(jsonObj): + schemeObj = None + if type(jsonObj) == list : + for dic in jsonObj : + schemeObj = JSONScheme() + if schemeObj.parseDictionary(dic) == False: + schemeObj = None + print "error - Fail to make scheme object." + break + + elif type(jsonObj) == dict : + schemeObj = JSONScheme() + if schemeObj.parseDictionary(jsonObj) == False : + schemeObj = None + print "error - Fail to make scheme object." + else : + print "error : no JSON Scheme" + return schemeObj + +def usage(): + usageString = 'Options:\n' + usageString += ' -v, --version shows version\n' + usageString += ' -h, --help shows help\n' + usageString += ' -p, --prefix= project prefix (default: S2M)\n' + usageString += ' -s, --suffix= classname suffix (default: JSONObject). Use "-s false" for no suffix\n' + usageString += ' -i, --input= metaJSON file to read\n' + usageString += ' -o, --output= output path of generated source codes (default: src)\n' + usageString += ' --template= template directory to use to generate code\n' + usageString += ' --package= name of the generated package (default: none)\n' + print(usageString) + sys.exit() + +def read_file(file_path): + basename, extension = os.path.splitext(file_path) + if extension == '.yaml': + return open_yaml_file(file_path) + else: + return openFileAndParseJSON(file_path) + +"Opens and read content of yaml file" +def open_yaml_file(file_path): + f = open(file_path) + try: + obj = yaml.load(f) + finally: + f.close() + return obj + +"Opens and read content of json file" +def openFileAndParseJSON(filePath): + f = open(filePath) + try: + obj = json.load(f) + finally: + f.close() + return obj + +def git_revision_short_hash(): + import subprocess + return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']) + +def version(): + git_rev = git_revision_short_hash() + if git_rev: + print("metaJSON version {}. git revision {}").format(__version__, git_rev) + else: + print("metaJSON version %s." % __version__) + sys.exit(0) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/metajson/template_code_generator.py b/metajson/template_code_generator.py new file mode 100644 index 0000000..6d03d17 --- /dev/null +++ b/metajson/template_code_generator.py @@ -0,0 +1,87 @@ +import os +import datetime +import time + +class TemplateCodeGenerator : + + TEMPLATE_EXT = ".mustache" + DEFAULT_TEMPLATE_PATH = "./metajson/templates" + + def __init__(self, template_path = DEFAULT_TEMPLATE_PATH, output_path = "classes", project_prefix = "S2M", package_name = ""): + self.project_prefix = project_prefix + self.package_name = package_name + self.template_path = template_path + if output_path.endswith("/"): + output_path = output_path[:-1] + self.output_path = output_path + self.read_template() + + ## main methods + def write_general_template_files(self): + for input_file in self.general_template_files: + output_file = self.create_output_file(input_file) + if output_file: + self.write_template(input_file, output_file) + else: + print "skip " + input_file + + ## internal use + def read_template(self): + self.json_template_files = [] + self.general_template_files = [] + for root, dirs, files in os.walk(self.template_path): + for name in files: + if name.startswith('.'): + continue + filepath = os.path.join(root, name) + basename, extension = os.path.splitext(filepath) + if extension == TemplateCodeGenerator.TEMPLATE_EXT: + template_basename, template_extension = os.path.splitext(basename) + if template_basename != basename: + self.json_template_files.append(filepath) + else: + filepath = os.path.join(root, name) + self.general_template_files.append(filepath) + + def create_output_file(self, filename): + return self.create_template_output_file(filename, None) + + def create_template_output_file(self, filename, classname): + start = filename.find(self.template_path) + + if start == -1: + new_filename = filename + else: + new_filename = filename[len(self.template_path):] + directories, new_filename = os.path.split(new_filename) + + # customize output filename + today = datetime.date.fromtimestamp(time.time()) + new_filename = self.replace_variables(new_filename, today) + if classname: + new_filename = new_filename.replace('_CLASSNAME_', classname) + new_filename = new_filename.replace(TemplateCodeGenerator.TEMPLATE_EXT, '') + if directories.startswith("/"): + directories = directories[1:] + + end_dir = os.path.join(self.output_path, directories) + if not os.path.exists(end_dir): + os.makedirs(end_dir) + return open(os.path.join(end_dir, new_filename), 'w') + + def replace_variables(self, text, today): + newtext = text.replace('_DATE_', "") + newtext = newtext.replace('_YEAR_', str(today.year)) + newtext = newtext.replace('_PREFIX_', self.project_prefix) + newtext = newtext.replace('_PACKAGE_', self.package_name) + return newtext + + def write_template(self, template, output): + today = datetime.date.fromtimestamp(time.time()) + # write content to ouptut + try: + for line in open(template): + newLine = self.replace_variables(line, today) + output.write(newLine) + finally : + output.close() diff --git a/metajson/templates/Android/_CLASSNAME_.java.mustache b/metajson/templates/Android/_CLASSNAME_.java.mustache new file mode 100644 index 0000000..d38502a --- /dev/null +++ b/metajson/templates/Android/_CLASSNAME_.java.mustache @@ -0,0 +1,278 @@ +/** +* {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}}.h +* +* Created by MetaJSONParser. +* Copyright (c) {{date}} SinnerSchrader Mobile. All rights reserved. +**/ + +package {{package}}; + +import android.util.Base64; + +import java.lang.IllegalArgumentException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import {{package}}.*; + +{{#baseTypeIsObject}} +public class {{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}} { +{{/baseTypeIsObject}} +{{^baseTypeIsObject}} +public class {{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}} extends {{baseClassName}} { +{{/baseTypeIsObject}} + + public {{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}}(JSONObject source) throws JSONException { + {{^baseTypeIsObject}} + super(source); + {{/baseTypeIsObject}} + {{#numberProperties}} + {{#required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.getDouble("{{name}}")); + {{/required}} + {{^required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.optDouble("{{name}}")); + {{/required}} + {{/numberProperties}} + {{#stringProperties}} + {{#required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.getString("{{name}}")); + {{/required}} + {{^required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.optString("{{name}}")); + {{/required}} + {{/stringProperties}} + {{#booleanProperties}} + {{#required}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = source.getBoolean("{{name}}"); + {{/required}} + {{^required}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = source.optBoolean("{{name}}"); + {{/required}} + {{/booleanProperties}} + {{#dateProperties}} + {{#required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(new Date(source.getLong("{{name}}"))); + {{/required}} + {{^required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(new Date(source.optLong("{{name}}"))); + {{/required}} + {{/dateProperties}} + {{#dataProperties}} + {{#required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(Base64.decode(source.getString("{{name}}"), Base64.DEFAULT)); + {{/required}} + {{^required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(Base64.decode(source.opString("{{name}}"), Base64.DEFAULT)); + {{/required}} + {{/dataProperties}} + {{#arrayProperties}} + {{#required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.getJSONArray("{{name}}")); + {{/required}} + {{^required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.optJSONArray("{{name}}")); + {{/required}} + {{/arrayProperties}} + {{#objectProperties}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = new {{className}}(source.optJSONObject("{{name}}")); + {{/objectProperties}} + {{#undefinedProperties}} + {{#required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.getJSONArray("{{name}}")); + {{/required}} + {{^required}} + set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(source.optJSONArray("{{name}}")); + {{/required}} + {{/undefinedProperties}} + } + +{{#numberProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private double m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/numberProperties}} +{{#stringProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private String m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/stringProperties}} +{{#booleanProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private boolean m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/booleanProperties}} +{{#dataProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private byte[] m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/dataProperties}} +{{#dateProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private Date m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/dateProperties}} +{{#arrayProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private JSONArray m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/arrayProperties}} +{{#objectProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private {{className}} m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/objectProperties}} +{{#undefinedProperties}} + {{#description}} + /** + * {{description}} + */ + {{/description}} + private JSONArray m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + +{{/undefinedProperties}} +{{#numberProperties}} + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(double newVal) { + {{#minValue}} + if (newVal < {{minValue}}) { + throw new IllegalArgumentException("Number " + newVal + " is smaller than {{minValue}}."); + } + {{/minValue}} + {{#maxValue}} + if (newVal > {{maxValue}}) { + throw new IllegalArgumentException("Number " + newVal + " is bigger than {{maxValue}}"); + } + {{/maxValue}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public double get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } + +{{/numberProperties}} +{{#stringProperties}} + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(String newVal) { + {{#maxLength}} + if ((newVal != null) && (newVal.length() > {{maxLength}})) { + throw new IllegalArgumentException("String is longer than " + {{maxLength}} + " characters."); + } + {{/maxLength}} + {{#minLength}} + if ((newVal != null) && (newVal.length() < {{minLength}})) { + throw new IllegalArgumentException("String is shorter than " + {{minLength}} + " characters."); + } + {{/minLength}} + {{#regex}} + if ((newVal != null) && (!newVal.matches("{{regex}}"))) { + throw new IllegalArgumentException("String \"" + newVal + "\" does not match regexp \"{{regex}}\"."); + } + {{/regex}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public String get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } + +{{/stringProperties}} +{{#booleanProperties}} + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(boolean newVal) { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public boolean get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } + +{{/booleanProperties}} +{{#dataProperties}} + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(byte[] newVal) { + {{#minLength}} + if ((newVal != null) && (newVal.length < {{minLength}})) { + throw new IllegalArgumentException("Data is only " + newVal.length + " bytes long (min: {{minLength}})"); + } + {{/minLength}} + {{#maxLength}} + if ((newVal != null) && (newVal.length > {{maxLength}})) { + throw new IllegalArgumentException("Data is " + newVal.length + " bytes long (max: {{maxLength}})"); + } + {{/maxLength}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public byte[] get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } + +{{/dataProperties}} +{{#dateProperties}} + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(Date newVal) { + {{#minValue}} + if ((newVal != null) && (newVal.getTime() < {{minValue}}) { + throw new IllegalArgumentException("Date " + newVal.getTime() + " is before {{minValue}}."); + } + {{/minValue}} + {{#maxValue}} + if ((newVal != null) && (newVal.getTime() > {{maxValue}}) { + throw new IllegalArgumentException("Date " + newVal.getTime() + " is after {{maxValue}}."); + } + {{/maxValue}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public Date get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } +{{/dateProperties}} +{{#arrayProperties}} +{{> metajson/templates/Android/array}} +{{/arrayProperties}} +{{#objectProperties}} + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}({{className}} newVal) { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public {{className}} get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } + +{{/objectProperties}} +{{#undefinedProperties}} +{{> metajson/templates/Android/array}} +{{/undefinedProperties}} + +} diff --git a/metajson/templates/Android/array.mustache b/metajson/templates/Android/array.mustache new file mode 100644 index 0000000..ad74b79 --- /dev/null +++ b/metajson/templates/Android/array.mustache @@ -0,0 +1,58 @@ + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}(JSONArray newVal) { + {{#minCount}} + if ((newVal != null) && (newVal.length() < {{minCount}})) { + throw new IllegalArgumentException("Array only has " + newVal.length() + " elements ({{minCount}} needed)."); + } + {{/minCount}} + {{#maxCount}} + if ((newVal != null) && (newVal.length() > {{maxCount}})) { + throw new IllegalArgumentException("Array has " + newVal.length() + " elements ({{maxCount}} allowed)."); + } + {{/maxCount}} + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}} = newVal; + } + + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsDouble(double newVal, int index) throws JSONException { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.put(index, newVal); + } + + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsString(String newVal, int index) throws JSONException { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.put(index, newVal); + } + + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsBoolean(boolean newVal, int index) throws JSONException { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.put(index, newVal); + } + + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsDate(Date newVal, int index) throws JSONException { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.put(index, newVal); + } + + public void set{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsArray(JSONArray newVal, int index) throws JSONException { + m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.put(index, newVal); + } + + public JSONArray get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}() { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}; + } + + public double get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsDouble(int index) { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.optDouble(index); + } + + public String get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsString(int index) { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.optString(index); + } + + public boolean get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsBoolean(int index) { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.optBoolean(index); + } + + public Date get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsDate(int index) { + return new Date(m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.optLong(index)); + } + + public JSONArray get{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}AsArray(int index) { + return m{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}.optJSONArray(index); + } + diff --git a/templates/APIParser/APIParser.h b/metajson/templates/iOS/APIParser/_PREFIX_APIParser.h similarity index 100% rename from templates/APIParser/APIParser.h rename to metajson/templates/iOS/APIParser/_PREFIX_APIParser.h diff --git a/templates/APIParser/APIParser.m b/metajson/templates/iOS/APIParser/_PREFIX_APIParser.m similarity index 100% rename from templates/APIParser/APIParser.m rename to metajson/templates/iOS/APIParser/_PREFIX_APIParser.m diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.h.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.h.mustache new file mode 100644 index 0000000..85ec9ee --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.h.mustache @@ -0,0 +1,87 @@ +// +// _{{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}}.h +// +// Created by MetaJSONParser. +// Copyright (c) {{date}} SinnerSchrader Mobile. All rights reserved. + +#import +{{^baseTypeIsObject}} +#import "{{baseClassName}}.h" +{{/baseTypeIsObject}} + +{{#custom_classes}} +@class {{.}}; +{{/custom_classes}} +@class {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}}; + +{{#baseTypeIsObject}} +@interface _{{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}} : NSObject +{{/baseTypeIsObject}} +{{^baseTypeIsObject}} +@interface _{{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}} : {{baseClassName}} +{{/baseTypeIsObject}} + +{{#numberProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) NSNumber *{{varName}}; +{{/numberProperties}} +{{#stringProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) NSString *{{varName}}; +{{/stringProperties}} +{{#booleanProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, assign) BOOL {{varName}}; +{{/booleanProperties}} +{{#dataProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) NSData *{{varName}}; +{{/dataProperties}} +{{#dateProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) NSDate *{{varName}}; +{{/dateProperties}} +{{#arrayProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) NSArray *{{varName}}; +{{/arrayProperties}} +{{#objectProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) {{className}} *{{varName}}; +{{/objectProperties}} +{{#undefinedProperties}} +{{#description}} +// {{description}} +{{/description}} +@property (nonatomic, strong) id {{varName}}; +{{/undefinedProperties}} + ++ ({{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}} *){{varName}}WithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +{{#baseTypeIsObject}} +- (NSDictionary *)propertyDictionary; +{{/baseTypeIsObject}} +{{#arrayProperties}} +{{> metajson/templates/iOS/AbstractInterfaceFiles/array_property}} +{{/arrayProperties}} +{{#undefinedProperties}} +{{> metajson/templates/iOS/AbstractInterfaceFiles/multiple_property}} +{{/undefinedProperties}} +{{^arrayProperties}} + +{{/arrayProperties}} +@end diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.m.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.m.mustache new file mode 100644 index 0000000..17ec4dd --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.m.mustache @@ -0,0 +1,524 @@ +// +// _{{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}}.m +// +// Created by MetaJSONParser. +// Copyright (c) {{date}} SinnerSchrader Mobile. All rights reserved. + +#import "{{prefix}}APIParser.h" +#import "NSString+RegExValidation.h" +#import "{{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}}.h" +{{#custom_classes}} +#import "{{.}}.h" +{{/custom_classes}} + + +@implementation _{{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}} + +#pragma mark - factory + ++ ({{prefix}}{{#_upper_camelcase}}{{name}}{{/_upper_camelcase}}{{suffix}} *){{varName}}WithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[{{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}} alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + {{#baseTypeIsObject}} + self = [super init]; + {{/baseTypeIsObject}} + {{^baseTypeIsObject}} + self = [super initWithDictionary:dic withError:error]; + {{/baseTypeIsObject}} + if (self) { + {{#numberProperties}} + self.{{varName}} = [{{prefix}}APIParser numberFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{#maxValue}} + if (self.{{varName}}.length > {{maxValue}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"max value validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/maxValue}} + {{#minValue}} + if (self.{{varName}}.length < {{minValue}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"min value validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/minValue}} + {{/numberProperties}} + {{#stringProperties}} + self.{{varName}} = [{{prefix}}APIParser stringFromResponseDictionary:dic forKey:@"{{name}}" acceptNumber:NO acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{#regex}} + if (self.{{varName}} && [self.{{varName}} matchesRegExString:@"{{& regex}}"] == NO) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/regex}} + {{#maxLength}} + if (self.{{varName}}.length > {{maxLength}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"max length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/maxLength}} + {{#minLength}} + if (self.{{varName}}.length < {{minLength}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"min length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/minLength}} + {{/stringProperties}} + {{#booleanProperties}} + self.{{varName}} = [{{prefix}}APIParser boolFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{/booleanProperties}} + {{#dataProperties}} + self.{{varName}} = [{{prefix}}APIParser dataFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{/dataProperties}} + {{#dateProperties}} + self.{{varName}} = [{{prefix}}APIParser dateWithTimeIntervalFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{/dateProperties}} + {{#arrayProperties}} + {{^hasOneSubtype}} + self.{{varName}} = [{{prefix}}APIParser arrayFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{/hasOneSubtype}} + {{#hasOneSubtype}} + {{#hasAnyType}} + self.{{varName}} = [{{prefix}}APIParser arrayFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + {{/hasAnyType}} + {{^hasAnyType}} + NSArray *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array = [{{prefix}}APIParser arrayFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + NSMutableArray *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [[NSMutableArray alloc] initWithCapacity:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array.count]; + for (NSUInteger loop = 0; loop < tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array.count; loop++) { + {{#hasStringType}} + NSString *tmpValue = [{{prefix}}APIParser stringFromResponseArray:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array atIndex:loop acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + {{/hasStringType}} + {{#hasNumberType}} + NSNumber *tmpValue = [{{prefix}}APIParser numberFromResponseArray:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array atIndex:loop acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + {{/hasNumberType}} + {{#hasDateType}} + NSDate *tmpValue = [{{prefix}}APIParser dateFromResponseArray:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array atIndex:loop acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + {{/hasDateType}} + {{^hasCustomType}} + if (*error) { + return self; + } + if (tmpValue) { + [tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} addObject:tmpValue]; + } + {{/hasCustomType}} + {{#hasCustomType}} + NSDictionary *tmpDic = [APIParser dictionaryFromResponseArray:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Array atIndex:loop acceptNil:NO error:error]; + if (*error) { + return self; + } + {{#subtypes}} + {{className}}*tmpObject = nil; + if (tmpDic) { + tmpObject= [[{{className}} alloc] initWithDictionary:tmpDic withError:error]; + if (*error) { + return self; + } + } + if (tmpObject) { + [tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} addObject:tmpObject]; + } + {{/subtypes}} + {{/hasCustomType}} + } + self.{{varName}} = [NSArray arrayWithArray:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}]; + {{/hasAnyType}} + {{/hasOneSubtype}} + {{#maxCount}} + if (self.{{varName}}.count > {{maxCount}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"max count validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/maxCount}} + {{#minCount}} + if (self.{{varName}}.count < {{minCount}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{varName}}", + @"key" : @"{{name}}", + @"reason" : @"min count validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + {{/minCount}} + {{/arrayProperties}} + {{#objectProperties}} + NSDictionary *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [APIParser dictionaryFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return self; + } + if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}) { + self.{{varName}}= [[{{className}} alloc] initWithDictionary:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} withError:error]; + if (*error) { + return self; + } + } + {{/objectProperties}} + {{#undefinedProperties}} + self.{{varName}} = [APIParser objectFromResponseDictionary:dic forKey:@"{{name}}" acceptNil:NO error:error]; + if (*error) { + return nil; + } + {{/undefinedProperties}} + } + return self; +} + +#pragma mark - getter +{{#arrayProperties}} +{{#hasMultipleSubtypes}} +{{#hasCustomType}} +{{#subtypes}} +{{#className}} + +- ({{className}} *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDictionary *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Dic = [APIParser dictionaryFromResponseArray:self.{{varName}} atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + {{className}} *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = nil; + if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Dic== nil) { + return nil; + } + if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Dic) { + tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}= [[{{className}} alloc] initWithDictionary:tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}Dic withError:error]; + if (*error) { + return nil; + } + } + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} +{{/className}} +{{/subtypes}} +{{/hasCustomType}} +{{#hasNumberType}} +{{#subtypes}} + +- (NSNumber *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSNumber *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [{{prefix}}APIParser numberFromResponseArray:self.{{varName}} atIndex:index acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return nil; + } + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} +{{/subtypes}} +{{/hasNumberType}} +{{#hasStringType}} +{{#subtypes}} + +- (NSString *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSString *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [{{prefix}}APIParser stringFromResponseArray:self.{{varName}} atIndex:index acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return nil; + } + {{#_subtype.maxLength}} + if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}.length > {{_subtype.maxLength}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{_subtype.name}}", + @"key" : @"{{_subtype.name}}", + @"reason" : @"max length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + {{/_subtype.maxLength}} + {{#_subtype.minLength}} + if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}.length < {{_subtype.minLength}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{_subtype.name}}", + @"key" : @"{{_subtype.name}}", + @"reason" : @"min length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + {{/_subtype.minLength}} + {{! to finish need to pass customClass regex...}} + {{#_subtype.regex}} + if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} && [tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} matchesRegExString:@"{{& _subtype.regex}}"] == NO) { + NSDictionary *userInfo = @{@"propertyName" : @"{{_subtype.name}}", + @"key" : @"{{_subtype.name}}", + @"reason" : @"validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + {{/_subtype.regex}} + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} +{{/subtypes}} +{{/hasStringType}} +{{#hasBooleanType}} +{{#subtypes}} + +- (BOOL){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + BOOL tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [{{prefix}}APIParser boolFromResponseArray:self.{{varName}} atIndex:index acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return nil; + } + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} +{{/subtypes}} +{{/hasBooleanType}} +{{#hasDateType}} +{{#subtypes}} + +- (NSDate *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDate *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [{{prefix}}APIParser dateWithTimeIntervalFromResponseArray:self.{{varName}} atIndex:index acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return nil; + } + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} +{{/subtypes}} +{{/hasDateType}} +{{#hasDataType}} +{{#subtypes}} + +- (NSData*){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSData* tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [{{prefix}}APIParser dataFromResponseArray:self.{{varName}} atIndex:index acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; + if (*error) { + return nil; + } + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} +{{/subtypes}} +{{/hasDataType}} +{{/hasMultipleSubtypes}} +{{#hasAnyType}} +- (id)objectIn{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error +{ + id tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [APIParser objectFromResponseArray:self.{{varName}} atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; +} + +{{/hasAnyType}} +{{/arrayProperties}} +{{#undefinedProperties}} +{{> metajson/templates/iOS/AbstractInterfaceFiles/multiple_property_implementation}} +{{/undefinedProperties}} + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + {{#numberProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/numberProperties}} + {{#stringProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/stringProperties}} + {{#booleanProperties}} + [coder encodeBool:self.{{varName}} forKey:@"{{name}}"]; + {{/booleanProperties}} + {{#dataProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/dataProperties}} + {{#dateProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/dateProperties}} + {{#msDateProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/msDateProperties}} + {{#arrayProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/arrayProperties}} + {{#objectProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/objectProperties}} + {{#undefinedProperties}} + [coder encodeObject:self.{{varName}} forKey:@"{{name}}"]; + {{/undefinedProperties}} +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + {{#numberProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/numberProperties}} + {{#stringProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/stringProperties}} + {{#booleanProperties}} + self.{{varName}} = [coder decodeBoolForKey:@"{{name}}"]; + {{/booleanProperties}} + {{#dataProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/dataProperties}} + {{#dateProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/dateProperties}} + {{#msDateProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/msDateProperties}} + {{#arrayProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/arrayProperties}} + {{#objectProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/objectProperties}} + {{#undefinedProperties}} + self.{{varName}} = [coder decodeObjectForKey:@"{{name}}"]; + {{/undefinedProperties}} + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + {{#baseTypeIsObject}} + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + {{/baseTypeIsObject}} + {{^baseTypeIsObject}} + NSMutableDictionary *dic = [[super propertyDictionary] mutableCopy]; + {{/baseTypeIsObject}} + {{#numberProperties}} + if (self.{{varName}}) { + [dic setObject:self.{{varName}} forKey:@"{{name}}"]; + } + {{/numberProperties}} + {{#stringProperties}} + if (self.{{varName}}) { + [dic setObject:self.{{varName}} forKey:@"{{name}}"]; + } + {{/stringProperties}} + {{#booleanProperties}} + if (self.{{varName}}) { + [dic setObject:[NSNumber numberWithBool:self.{{varName}}] forKey:@"{{name}}"]; + } + {{/booleanProperties}} + {{#dataProperties}} + if (self.{{varName}}) { + [dic setObject:self.{{varName}} forKey:@"{{name}}"]; + } + {{/dataProperties}} + {{#dateProperties}} + if (self.{{varName}}) { + [dic setObject:[NSNumber numberWithInteger:[[NSNumber numberWithDouble:[self.{{varName}} timeIntervalSince1970]] longValue]] forKey:@"{{name}}"]; + } + {{/dateProperties}} + {{#arrayProperties}} + {{#hasMultipleSubtypes}} + if (self.{{varName}}) { + [dic setObject:self.{{varName}} forKey:@"{{name}}"]; + } + {{/hasMultipleSubtypes}} + {{^hasMultipleSubtypes}} + {{#hasCustomType}} + {{#subtypes}} + if (self.{{varName}}) { + NSMutableArray *tmpArray = [[NSMutableArray alloc] init]; + for ({{className}} *tmpObj in self.{{varName}}) { + [tmpArray addObject:[tmpObj propertyDictionary]]; + } + [dic setObject:tmpArray forKey:@"{{name}}"]; + } + {{/subtypes}} + {{/hasCustomType}} + {{^hasCustomType}} + if (self.{{varName}}) { + [dic setObject:self.{{varName}} forKey:@"{{name}}"]; + } + {{/hasCustomType}} + {{/hasMultipleSubtypes}} + {{/arrayProperties}} + {{#objectProperties}} + if (self.{{varName}}) { + [dic setObject:[self.{{varName}} propertyDictionary] forKey:@"{{name}}"]; + } + {{/objectProperties}} + {{#undefinedProperties}} + if (self.{{varName}}) { + [dic setObject:self.{{varName}} forKey:@"{{name}}"]; + } + {{/undefinedProperties}} + return dic; +} + +{{#baseTypeIsObject}} +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} +{{/baseTypeIsObject}} + +@end diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/array_property.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/array_property.mustache new file mode 100644 index 0000000..13a6273 --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/array_property.mustache @@ -0,0 +1,37 @@ +{{#hasMultipleSubtypes}} +{{#hasCustomType}} +{{#subtypes}} +{{#className}} +- ({{className}} *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/className}} +{{/subtypes}} +{{/hasCustomType}} +{{#hasNumberType}} +{{#subtypes}} +- (NSNumber *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/subtypes}} +{{/hasNumberType}} +{{#hasStringType}} +{{#subtypes}} +- (NSString *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/subtypes}} +{{/hasStringType}} +{{#hasBooleanType}} +{{#subtypes}} +- (BOOL ){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/subtypes}} +{{/hasBooleanType}} +{{#hasDateType}} +{{#subtypes}} +- (NSDate *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/subtypes}} +{{/hasDateType}} +{{#hasDataType}} +{{#subtypes}} +- (NSData *){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/subtypes}} +{{/hasDataType}} +{{/hasMultipleSubtypes}} +{{#hasAnyType}} +- (id){{subtype}}In{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}AtIndex:(NSUInteger)index withError:(NSError **)error; +{{/hasAnyType}} diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/multiple_property.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/multiple_property.mustache new file mode 100644 index 0000000..5292a88 --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/multiple_property.mustache @@ -0,0 +1,19 @@ +{{#hasCustomType}} +{{#className}} +- ({{className}} *){{name}}As{{#_upper_camelcase}}{{type}}{{/_upper_camelcase}}:(NSError **)error; +{{/className}} +{{^className}} +- (NSString *){{name}}As{{#_upper_camelcase}}{{type}}{{/_upper_camelcase}}:(NSError **)error; +{{/className}} +{{/hasCustomType}} +{{#hasNumberType}} +- (NSNumber *){{name}}AsNumber:(NSError **)error; +{{/hasNumberType}} +{{#hasStringType}} +{{#types}} +- (NSString *){{name}}As{{#_upper_camelcase}}{{type}}{{/_upper_camelcase}}:(NSError **)error; +{{/types}} +{{/hasStringType}} +{{#hasDateType}} +- (NSDate *){{name}}AsDate:(NSError **)error; +{{/hasDateType}} diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/multiple_property_implementation.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/multiple_property_implementation.mustache new file mode 100644 index 0000000..066a573 --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/multiple_property_implementation.mustache @@ -0,0 +1,31 @@ +{{#hasCustomType}} +{{#className}} + +- ({{className}} *){{name}}As{{#_upper_camelcase}}{{type}}{{/_upper_camelcase}}:(NSError **)error +{ + {{> metajson/templates/iOS/AbstractInterfaceFiles/number_property}} +} +{{/className}} +{{/hasCustomType}} +{{#hasNumberType}} + +- (NSNumber *){{name}}AsNumber:(NSError **)error +{ + {{> metajson/templates/iOS/AbstractInterfaceFiles/number_property}} +} +{{/hasNumberType}} +{{#hasStringType}} +{{#types}} +- (NSString *){{name}}As{{#_upper_camelcase}}{{type}}{{/_upper_camelcase}}:(NSError **)error +{ + {{> metajson/templates/iOS/AbstractInterfaceFiles/string_property}} +} +{{/types}} +{{/hasStringType}} +{{#hasDateType}} + +- (NSDate *){{name}}AsDate:(NSError **)error +{ + +} +{{/hasDateType}} diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/number_property.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/number_property.mustache new file mode 100644 index 0000000..fabec55 --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/number_property.mustache @@ -0,0 +1,7 @@ +if (!self.{{varName}}) return nil; +NSDictionary *new{{varName}}Dic = @{@"{{name}}" : self.{{varName}}}; +NSNumber *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [APIParser numberFromResponseDictionary:new{{varName}}Dic forKey:@"{{name}}" acceptNil:NO error:error]; +if (*error) { + return nil; +} +return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; diff --git a/metajson/templates/iOS/AbstractInterfaceFiles/string_property.mustache b/metajson/templates/iOS/AbstractInterfaceFiles/string_property.mustache new file mode 100644 index 0000000..1e7eea1 --- /dev/null +++ b/metajson/templates/iOS/AbstractInterfaceFiles/string_property.mustache @@ -0,0 +1,49 @@ +if (!self.{{varName}}) return nil; +NSDictionary *new{{varName}}Dic = @{@"{{varName}}" : self.{{varName}}}; +NSString *tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} = [APIParser stringFromResponseDictionary:new{{varName}}Dic forKey:@"{{name}}" acceptNumber:NO acceptNil:{{#required}}NO{{/required}}{{^required}}YES{{/required}} error:error]; +if (*error) { + return nil; +} +{{#_type}} +if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} == nil) { + return nil; +} +{{/_type}} +{{#_type.maxLength}} +if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}.length > {{_type.maxLength}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{_type.name}}", + @"key" : @"{{_type.name}}", + @"reason" : @"max length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; +} +{{/_type.maxLength}} +{{#_type.minLength}} +if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}.length < {{_type.minLength}}) { + NSDictionary *userInfo = @{@"propertyName" : @"{{_type.name}}", + @"key" : @"{{_type.name}}", + @"reason" : @"min length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; +} +{{/_type.minLength}} +{{! to finish need to pass customClass regex...}} +{{#_type.regex}} +if (tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} && [tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}} matchesRegExString:@"{{& _type.regex}}"] == NO) { + NSDictionary *userInfo = @{@"propertyName" : @"{{_type.name}}", + @"key" : @"{{_type.name}}", + @"reason" : @"validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:k{{prefix}}ErrorDomain_parser code:k{{prefix}}ErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; +} +{{/_type.regex}} +return tmp{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}; diff --git a/templates/NSString+RegExValidation.h b/metajson/templates/iOS/Utilities/NSString+RegExValidation.h similarity index 100% rename from templates/NSString+RegExValidation.h rename to metajson/templates/iOS/Utilities/NSString+RegExValidation.h diff --git a/templates/NSString+RegExValidation.m b/metajson/templates/iOS/Utilities/NSString+RegExValidation.m similarity index 100% rename from templates/NSString+RegExValidation.m rename to metajson/templates/iOS/Utilities/NSString+RegExValidation.m diff --git a/metajson/templates/iOS/_CLASSNAME_.h.mustache b/metajson/templates/iOS/_CLASSNAME_.h.mustache new file mode 100644 index 0000000..1a1bb94 --- /dev/null +++ b/metajson/templates/iOS/_CLASSNAME_.h.mustache @@ -0,0 +1,10 @@ +// +// {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}}.h +// +// Created by MetaJSONParser. +// Copyright (c) {{date}} SinnerSchrader Mobile. All rights reserved. + +#import "_{{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}}.h" +@interface {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}} : _{{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}} + +@end diff --git a/metajson/templates/iOS/_CLASSNAME_.m.mustache b/metajson/templates/iOS/_CLASSNAME_.m.mustache new file mode 100644 index 0000000..7601b88 --- /dev/null +++ b/metajson/templates/iOS/_CLASSNAME_.m.mustache @@ -0,0 +1,15 @@ +// +// {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}}.m +// +// Created by MetaJSONParser. +// Copyright (c) {{date}} SinnerSchrader Mobile. All rights reserved. + +#import "{{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}}.h" + +@interface {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}} () + +@end + +@implementation {{prefix}}{{#_upper_camelcase}}{{varName}}{{/_upper_camelcase}}{{suffix}} + +@end diff --git a/readJSON.py b/readJSON.py deleted file mode 100755 index eba084b..0000000 --- a/readJSON.py +++ /dev/null @@ -1,203 +0,0 @@ -''' -The MIT License (MIT) - -Copyright (c) 2013 SinnerSchrader Mobile GmbH - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -''' - -__version__ = "2.7.2" - -import json -import os -import glob -import shutil -import sys, getopt -from JSONScheme import * -from ObjectiveCCodeGenerator import * -from JavaCodeGenerator import * - - -jsonfiles = [] -inputfile = 'do you have files?' -projectPrefix = '' -target = 'iOS' -dirPathToSaveCodes = './src' -objectSuffix = "JSONObject" - -usageString = '\nreadJSON.py [ -p | -t | -o | -s ] [-i]\n' -usageString += 'Options:\n' -usageString += ' -h, --help shows help\n' -usageString += ' -p, --prefix= project prefix (default: S2M)\n' -usageString += ' -s, --suffix= classname suffix (default: JSONObject). Use "-s false" for no suffix\n' -usageString += ' -t, --target= target platform iOS or Android (default: iOS)\n' -usageString += ' -i, --input= meta-JSON file to read\n' -usageString += ' -o, --output= ouput path of generated source codes\n' - -if __name__ == "__main__": - argv = sys.argv[1:] - try: - opts, args = getopt.getopt(argv,"ho:p:s:t:i:",["prefix=","suffix=","target=","input=","output="]) - except getopt.GetoptError: - print usageString - sys.exit(2) - - for opt, arg in opts: - if opt in ("-h", "--help"): - print usageString - sys.exit() - elif opt in ("-p", "--prefix"): - projectPrefix = arg - elif opt in ("-t", "--target"): - target = arg - elif opt in ("-i", "--input"): - inputfile = arg - elif opt in ("-o", "--output"): - dirPathToSaveCodes = arg - elif opt in ("-s", "--suffix"): - objectSuffix = arg - if objectSuffix == "false": - objectSuffix = "" - - addFiles = False - for arg in argv : - if arg.endswith(inputfile) : - jsonfiles.append(inputfile) - addFiles = True - continue - - if arg.startswith('-') and addFiles : - addFiles = False - break - - if addFiles : - jsonfiles.append(arg) - -if target == 'none' : - print 'error - target platform is not defined' - print usageString - sys.exit() - -if len(jsonfiles) == 0 : - print 'error - meta JSON file is not defined' - print usageString - sys.exit() - - - -templatePath = os.path.abspath( __file__ ) -templatePath = templatePath.replace('/readJSON.py', '/templates') - -if not os.path.exists(dirPathToSaveCodes): - os.makedirs(dirPathToSaveCodes) - -def openFileAndParseJSON(filePath): - f = open(filePath) - - try: - obj = json.load(f) - finally: - f.close() - - return obj - -iOS = False -Android = False -if target == 'iOS' : - iOS = True -elif target == 'Android' : - Android = True -else : - print 'error - unknown target platform : ' + target - print usageString - sys.exit() - - -hasError = False - -if iOS : - if dirPathToSaveCodes.endswith("/") : - dirPathToSaveCodes = dirPathToSaveCodes[:-1] - - if os.path.exists(dirPathToSaveCodes+ "/abstractInterfaceFiles"): - shutil.rmtree(dirPathToSaveCodes + "/abstractInterfaceFiles") - - templateCodeGen = TemplateCodeGenerator() - templateCodeGen.templatePath = templatePath - templateCodeGen.projectPrefix = projectPrefix - templateCodeGen.dirPath = dirPathToSaveCodes - templateCodeGen.writeTemplates() - -JSONScheme.projectPrefix = projectPrefix -JSONScheme.objectSuffix = objectSuffix - -print "\nGenerate source codes for " + target + ", with Project Prefix \'" + projectPrefix + "\' and suffix \'" + objectSuffix + "\'" -print "Output path : \'" + dirPathToSaveCodes + "\'\n" - -for filePath in jsonfiles : - print "read " + filePath + " to parse ...." - - jsonObj = openFileAndParseJSON(filePath) - - if type(jsonObj) == list : - for dic in jsonObj : - schemeObj = JSONScheme() - schemeObj.projectPrefix = projectPrefix - schemeObj.objectSuffix = objectSuffix - if schemeObj.parseDictionary(dic) == False: - hasError = True - break - - elif type(jsonObj) == dict : - schemeObj = JSONScheme() - if schemeObj.parseDictionary(jsonObj) == False : - hasError = True - - else : - hasError = True - print "error : no JSON Scheme" - break; - - if hasError : - print "error - Fail to make scheme object." - break; - - if hasError : - break - - if not hasError: - codeGen = 0 - - if Android : - codeGen = JavaCodeGenerator() - else : - codeGen = ObjectiveCCodeGenerator() - - codeGen.projectPrefix = projectPrefix - codeGen.dirPath = dirPathToSaveCodes - codeGen.objectSuffix = objectSuffix - allSchemes = JSONScheme.JSONSchemeDic - codeGen.JSONSchemeDic = allSchemes - - rootDic = allSchemes["ROOT"] - allRootKeys = rootDic.keys() - for typeName in rootDic : - obj = rootDic[typeName]; - if obj.isNaturalType() == False : - codeGen.make(obj) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2f7ba31 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +nose +pystache +pyyaml diff --git a/samples.product.yaml b/samples.product.yaml new file mode 100644 index 0000000..0753ce7 --- /dev/null +++ b/samples.product.yaml @@ -0,0 +1,33 @@ +- + name: sender + base-type: object + description: 'sender info.' + property: [{ name: senderName, base-type: string, required: 1 }, { name: previewImageURL, base-type: string, required: 1 }] +- + name: senderList + base-type: object + description: 'the list of senders.' + property: [{ name: listTitle, base-type: string, description: 'the title of sender list', required: 1 }, { name: senders, base-type: array, description: 'the array of Sender', subType: sender, required: 1 }] +- + name: senderList2 + base-type: senderList + description: 'the list of senders2.' + property: [{ name: listSubTitle, base-type: string, description: 'the title of sender list', required: 1 }] +- + name: senderGroup + base-type: object + description: 'the list of senders.' + property: [{ name: digitalSenders, base-type: array, subType: [senderList, senderList2, number, string, boolean, date, data], description: 'the array of sender list' }, { name: HDOptions, base-type: array, description: 'the array of sender list', subType: [senderList, senderList2] }, { name: DTVHighlights, base-type: array, description: 'the array of sender list', subType: [string, titleString], maxCount: 6, minCount: 2 }, { name: IPTVSenders, base-type: array, description: 'the array of sender list', subType: any, maxCount: 6, minCount: 2 }] +- + name: titleString + base-type: string + description: 'the title of product' + minLength: 10 + maxLength: 20 + regex: '[a-z0-9]:10' + required: 1 +- + name: ProductDetail + base-type: object + description: 'Product details.' + property: [{ name: type, base-type: number, description: 'the type of product', required: 1 }, { name: advantage, base-type: number, required: 1 }, { name: teaserURL, base-type: string, description: 'teaser image url of product', required: 1 }, { name: telephoneFlatrate, base-type: string, description: 'telephone Flatrate option string' }, { name: includeHardware, base-type: boolean, required: 1 }, { name: senderInfo, base-type: senderGroup }, { name: anyProperty, base-type: any, required: 1 }, { name: title, base-type: [titleString, string], description: 'the title of product', required: 1 }, { name: download, base-type: [number, string], description: 'download speed (Mbit/s)', required: 1 }, { name: upload, base-type: [number, string], description: 'upload speed (Mbit/s)', required: 1 }] diff --git a/samples/product.json b/samples/product.json index 2fb2761..71efdc1 100644 --- a/samples/product.json +++ b/samples/product.json @@ -60,7 +60,8 @@ [ { "name" : "digitalSenders", - "base-type" : ["senderList", "senderList2", "number", "string", "boolean", "date", "data"], + "base-type" : "array", + "subType" : ["senderList", "senderList2", "number", "string", "boolean", "date", "data"], "description" : "the array of sender list" }, { @@ -103,15 +104,14 @@ "property" : [ { - "name" : "title", - "base-type" : ["titleString","string"], - "description" : "the title of product", + "name" : "type", + "base-type" : "number", + "description" : "the type of product", "required" : 1 }, { - "name" : "type", + "name" : "advantage", "base-type" : "number", - "description" : "the type of product", "required" : 1 }, { @@ -120,31 +120,19 @@ "description" : "teaser image url of product", "required" : 1 }, - { - "name" : "download", - "base-type" : ["number", "string"], - "description" : "download speed (Mbit/s)", - "required" : 1 - }, - { - "name" : "upload", - "base-type" : ["number", "string"], - "description" : "upload speed (Mbit/s)", - "required" : 1 - }, { "name" : "telephoneFlatrate", "base-type" : "string", "description" : "telephone Flatrate option string" }, - { - "name" : "senderInfo", - "base-type" : "senderGroup" - }, { "name" : "includeHardware", "base-type" : "boolean", "required" : 1 + }, + { + "name" : "senderInfo", + "base-type" : "senderGroup" }, { "name" : "anyProperty", @@ -152,10 +140,25 @@ "required" : 1 }, { - "name" : "advantage", - "base-type" : "number", + "name" : "title", + "base-type" : ["titleString","string"], + "description" : "the title of product", + "required" : 1 + }, + + { + "name" : "download", + "base-type" : ["number", "string"], + "description" : "download speed (Mbit/s)", + "required" : 1 + }, + { + "name" : "upload", + "base-type" : ["number", "string"], + "description" : "upload speed (Mbit/s)", "required" : 1 } + ] } -] \ No newline at end of file +] diff --git a/samples/product.yaml b/samples/product.yaml new file mode 100644 index 0000000..0753ce7 --- /dev/null +++ b/samples/product.yaml @@ -0,0 +1,33 @@ +- + name: sender + base-type: object + description: 'sender info.' + property: [{ name: senderName, base-type: string, required: 1 }, { name: previewImageURL, base-type: string, required: 1 }] +- + name: senderList + base-type: object + description: 'the list of senders.' + property: [{ name: listTitle, base-type: string, description: 'the title of sender list', required: 1 }, { name: senders, base-type: array, description: 'the array of Sender', subType: sender, required: 1 }] +- + name: senderList2 + base-type: senderList + description: 'the list of senders2.' + property: [{ name: listSubTitle, base-type: string, description: 'the title of sender list', required: 1 }] +- + name: senderGroup + base-type: object + description: 'the list of senders.' + property: [{ name: digitalSenders, base-type: array, subType: [senderList, senderList2, number, string, boolean, date, data], description: 'the array of sender list' }, { name: HDOptions, base-type: array, description: 'the array of sender list', subType: [senderList, senderList2] }, { name: DTVHighlights, base-type: array, description: 'the array of sender list', subType: [string, titleString], maxCount: 6, minCount: 2 }, { name: IPTVSenders, base-type: array, description: 'the array of sender list', subType: any, maxCount: 6, minCount: 2 }] +- + name: titleString + base-type: string + description: 'the title of product' + minLength: 10 + maxLength: 20 + regex: '[a-z0-9]:10' + required: 1 +- + name: ProductDetail + base-type: object + description: 'Product details.' + property: [{ name: type, base-type: number, description: 'the type of product', required: 1 }, { name: advantage, base-type: number, required: 1 }, { name: teaserURL, base-type: string, description: 'teaser image url of product', required: 1 }, { name: telephoneFlatrate, base-type: string, description: 'telephone Flatrate option string' }, { name: includeHardware, base-type: boolean, required: 1 }, { name: senderInfo, base-type: senderGroup }, { name: anyProperty, base-type: any, required: 1 }, { name: title, base-type: [titleString, string], description: 'the title of product', required: 1 }, { name: download, base-type: [number, string], description: 'download speed (Mbit/s)', required: 1 }, { name: upload, base-type: [number, string], description: 'upload speed (Mbit/s)', required: 1 }] diff --git a/samples/test.json b/samples/test.json deleted file mode 100644 index 5c40538..0000000 --- a/samples/test.json +++ /dev/null @@ -1,114 +0,0 @@ -[ - { - "name" : "mySession", - "base-type" : "object", - "description" : "session has session id and session expire date.", - "property" : - [ - { - "name" : "sessionID", - "base-type" : "string", - "description" : "session string after login", - "maxLength" : 50, - "minLength" : 20, - "required" : 1 - }, - { - "name" : "expirationDate", - "base-type" : "date", - "description" : "Experation date of session", - "maxValue" : 183759284, - "required" : 1 - } - ] - }, - { - "name" : "userAddress", - "base-type" : "object", - "description" : "user address type.", - "property" : - [ - { - "name" : "street", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "houseNumber", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "additionalAddress", - "base-type" : "string", - "required" : 0 - }, - { - "name" : "City", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "Country", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "zipCode", - "base-type" : "string", - "required" : 1 - } - ] - }, - { - "name" : "person", - "base-type" : "object", - "property" : - [ - { - "name" : "firstName", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "lastName", - "base-type" : "string", - "required" : 1 - } - ] - }, - { - "name" : "user", - "base-type" : "person", - "description" : "test description of user type.", - "property" : - [ - { - "name" : "email", - "base-type" : "string", - "regex" : "[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,4}" - }, - { - "name" : "family", - "base-type" : "array", - "subType" : ["person", "userAddress", "string"], - "required" : 1 - }, - { - "name" : "userID", - "base-type" : "string", - "required" : 1 - }, - { - "name" : "address", - "base-type" : "userAddress", - "required" : 1 - }, - { - "name" : "session", - "base-type" : "mySession", - "required" : 1 - } - ] - } -] diff --git a/samples/test_class.json b/samples/test_class.json new file mode 100644 index 0000000..3b01e7f --- /dev/null +++ b/samples/test_class.json @@ -0,0 +1,20 @@ +[ + { + "name" : "sender", + "base-type" : "object", + "description" : "sender info.", + "property" : + [ + { + "name" : "senderName", + "base-type" : "string", + "required" : 1 + }, + { + "name" : "previewImageURL", + "base-type" : "string", + "required" : 1 + } + ] + } +] diff --git a/samples/test_string_options.json b/samples/test_string_options.json new file mode 100644 index 0000000..5926b6e --- /dev/null +++ b/samples/test_string_options.json @@ -0,0 +1,20 @@ +[ + { + "name" : "login", + "base-type" : "object", + "property" : + [ + { + "name": "emailString", + "base-type": "string", + "regex": "[a-z0-9!#$%&'*+/=?^_`{|}~-](?:\\\\.[a-z0-9!#$%&'*/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" + }, + { + "name" : "password", + "base-type" : "string", + "minLength": 3, + "maxLength": 12 + } + ] + } +] diff --git a/samples/test_subclass.json b/samples/test_subclass.json new file mode 100644 index 0000000..24df52b --- /dev/null +++ b/samples/test_subclass.json @@ -0,0 +1,28 @@ +[ + { + "name" : "motherClass", + "base-type" : "object", + "property" : + [ + { + "name" : "id", + "base-type" : "string", + "required" : 1 + } + ] + }, + { + "name" : "subClass", + "base-type" : "motherClass", + "description" : "subclass of motherClass", + "property" : + [ + { + "name" : "name", + "base-type" : "string", + "required" : 0 + } + ] + } + +] diff --git a/samples/test_types.json b/samples/test_types.json new file mode 100644 index 0000000..833edf0 --- /dev/null +++ b/samples/test_types.json @@ -0,0 +1,51 @@ +[ + { + "name": "customNumber", + "base-type": "number", + "minLength": 1, + "maxLength": 10 + }, + { + "name": "superObject", + "base-type": "object", + "property": [ + { + "name": "isBoolean", + "base-type": "boolean" + }, + { + "name": "myData", + "base-type": "data" + }, + { + "name": "creationDate", + "base-type": "date" + }, + { + "name": "objectWithoutSubtypes", + "base-type": "array" + }, + { + "name": "numbers", + "base-type": "array", + "subType": "number" + }, + { + "name": "stringsAndDates", + "base-type": "array", + "subType": ["string", "date"] + }, + { + "name": "customNumbers", + "base-type": "array", + "subType": "customNumber" + }, + { + "name": "stringsAndCustomNumbers", + "base-type": "array", + "subType": ["string", "customNumber"] + } + + ] + } +] diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..7cec205 --- /dev/null +++ b/setup.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +import re +from setuptools import setup + +version = re.search( + '^__version__\s*=\s*"(.*)"', + open('metajson/readJSON.py').read(), + re.M + ).group(1) + + +with open("README.md", "rb") as f: + long_descr = f.read().decode("utf-8") + +setup( + name = "metaJSON", + packages = ["metajson"], + entry_points = { + "console_scripts": ['metajson = metajson.readJSON:main'] + }, + install_requires = ['pystache', 'pyyaml'], + tests_require = ['nose'], + include_package_data = True, #will include files listed in MANIFEST.in + version = version, + description = 'metaJSON provides a meta language to generate object models for several languages. The generated classes can easily be used for the client-server communication.', + url = 'https://github.com/sinnerschrader-mobile/metaJSON.git', + license = 'MIT', + long_description = long_descr, + ) diff --git a/test/SourceCodeGenerator_test.py b/test/SourceCodeGenerator_test.py new file mode 100644 index 0000000..e291e99 --- /dev/null +++ b/test/SourceCodeGenerator_test.py @@ -0,0 +1,154 @@ +from metajson.SourceCodeGenerator import SourceCodeGenerator +from metajson.JSONScheme import * + +import pickle +import unittest +import sys +import os +import datetime + +class TestSourceCodeGenerator(unittest.TestCase): + def setUp(self): + self.gen = SourceCodeGenerator() + self.maxDiff = None + self.default_folder = 'test/data/' + + def tearDown(self): + del self.gen + + def template_file_path(self, filename) : + templatePath = os.path.realpath( __file__ ) + templatePath = templatePath.replace(os.path.basename( __file__ ), '../metajson/templates/iOS') + return os.path.join(templatePath, filename) + + def human_header_content(self, schemeObj) : + template_file = open(self.template_file_path("_CLASSNAME_.h.mustache"), "r") + return self.gen.render(schemeObj, template_file.read()) + + def human_source_content(self, schemeObj) : + template_file = open(self.template_file_path("_CLASSNAME_.m.mustache"), "r") + return self.gen.render(schemeObj, template_file.read()) + + def machine_header_content(self, schemeObj) : + template_file = open(self.template_file_path("AbstractInterfaceFiles/__CLASSNAME_.h.mustache"), "r") + return self.gen.render(schemeObj, template_file.read()) + + def machine_source_content(self, schemeObj) : + template_file = open(self.template_file_path("AbstractInterfaceFiles/__CLASSNAME_.m.mustache"), "r") + return self.gen.render(schemeObj, template_file.read()) + + def assert_content_file(self, filename, content): + with open(filename, 'r') as content_file: + expected_result = content_file.read() + # All reference files have a timestamp of 2014 so we tweak our generated code to match them. + self.assertMultiLineEqual(content.replace(str(datetime.datetime.now().year), "2014"), expected_result) + +class TestSampleTestClassCase(TestSourceCodeGenerator): + def setUp(self): + super(TestSampleTestClassCase, self).setUp() + self.test_file_path = self.default_folder + 'test_class' + self.scheme_object = pickle.load(open(self.test_file_path + '.p', 'rb')) + + + def test_human_header_content(self): + result = self.human_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/S2MSenderJSONObject.h", result) + + def test_human_source_content(self): + result = self.human_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/S2MSenderJSONObject.m", result) + + def test_machine_source_content(self): + result = self.machine_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_S2MSenderJSONObject.m", result) + + def test_machine_header_content(self): + result = self.machine_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_S2MSenderJSONObject.h", result) + + +class TestSampleTestStringOptionsCase(TestSourceCodeGenerator): + def setUp(self): + super(TestSampleTestStringOptionsCase, self).setUp() + self.test_file_path = self.default_folder + 'test_string_options' + self.scheme_object = pickle.load(open(self.test_file_path + '.p', 'rb')) + + def test_machine_source_content(self): + result = self.machine_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_S2MLoginJSONObject.m", result) + + def test_machine_header_content(self): + result = self.machine_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_S2MLoginJSONObject.h", result) + +class TestSampleTestSubclassCase(TestSourceCodeGenerator): + def setUp(self): + super(TestSampleTestSubclassCase, self).setUp() + scheme = pickle.load(open(self.default_folder + '/test_subclass_scheme.p', 'rb')) + JSONScheme.JSONSchemeDic = scheme + + +class TestSampleTestSubclassMotherCase(TestSampleTestSubclassCase): + def setUp(self): + super(TestSampleTestSubclassMotherCase, self).setUp() + self.test_file_path = self.default_folder + 'test_subclass' + self.scheme_object = pickle.load(open(self.default_folder + '/test_subclass_motherClass.p', 'rb')) + + def test_human_header_content(self): + result = self.human_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/MotherClassJSONObject.h", result) + + def test_human_source_content(self): + result = self.human_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/MotherClassJSONObject.m", result) + + def test_machine_source_content(self): + result = self.machine_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_MotherClassJSONObject.m", result) + + def test_machine_header_content(self): + result = self.machine_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_MotherClassJSONObject.h", result) + +class TestSampleTestSubclassSubclassCase(TestSampleTestSubclassCase): + def setUp(self): + super(TestSampleTestSubclassSubclassCase, self).setUp() + self.test_file_path = self.default_folder + 'test_subclass' + self.scheme_object = pickle.load(open(self.default_folder + '/test_subclass_subClass.p', 'rb')) + + def test_human_header_content(self): + result = self.human_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/SubClassJSONObject.h", result) + + def test_human_source_content(self): + result = self.human_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/SubClassJSONObject.m", result) + + def test_machine_source_content(self): + result = self.machine_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_SubClassJSONObject.m", result) + + def test_machine_header_content(self): + result = self.machine_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_SubClassJSONObject.h", result) + +class TestSampleTestTypesCase(TestSourceCodeGenerator): + def setUp(self): + super(TestSampleTestTypesCase, self).setUp() + scheme = pickle.load(open(self.default_folder + '/test_types_scheme.p', 'rb')) + JSONScheme.JSONSchemeDic = scheme + + self.test_file_path = self.default_folder + 'test_types' + self.scheme_object = pickle.load(open(self.default_folder + '/test_types_superObject.p', 'rb')) + + def test_machine_header_content(self): + result = self.machine_header_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_S2MSuperObjectJSONObject.h", result) + + def test_machine_source_content(self): + result = self.machine_source_content(self.scheme_object) + self.assert_content_file(self.test_file_path + "/_S2MSuperObjectJSONObject.m", result) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/data/product/AbstractInterfaceFiles/_ProductDetailJSONObject.h b/test/data/product/AbstractInterfaceFiles/_ProductDetailJSONObject.h new file mode 100644 index 0000000..5437e8c --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_ProductDetailJSONObject.h @@ -0,0 +1,44 @@ +// +// _ProductDetailJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class SenderGroupJSONObject; + +@class ProductDetailJSONObject; + +@interface _ProductDetailJSONObject : NSObject + + +// the type of product +@property (nonatomic, strong) NSNumber *type; +@property (nonatomic, strong) NSNumber *advantage; +// teaser image url of product +@property (nonatomic, strong) NSString *teaserURL; +// telephone Flatrate option string +@property (nonatomic, strong) NSString *telephoneFlatrate; +@property (nonatomic, assign) BOOL includeHardware; +@property (nonatomic, strong) SenderGroupJSONObject *senderInfo; +@property (nonatomic, strong) id anyProperty; +// the title of product +@property (nonatomic, strong) id title; +// download speed (Mbit/s) +@property (nonatomic, strong) id download; +// upload speed (Mbit/s) +@property (nonatomic, strong) id upload; + ++ (ProductDetailJSONObject *)ProductDetailWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; +- (NSString *)titleAsTitleString:(NSError **)error; +- (NSString *)titleAsString:(NSError **)error; +- (NSNumber *)downloadAsNumber:(NSError **)error; +- (NSString *)downloadAsString:(NSError **)error; +- (NSNumber *)uploadAsNumber:(NSError **)error; +- (NSString *)uploadAsString:(NSError **)error; + +@end + diff --git a/test/data/product/AbstractInterfaceFiles/_ProductDetailJSONObject.m b/test/data/product/AbstractInterfaceFiles/_ProductDetailJSONObject.m new file mode 100644 index 0000000..66b715b --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_ProductDetailJSONObject.m @@ -0,0 +1,253 @@ +// +// _ProductDetailJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "ProductDetailJSONObject.h" +#import "SenderGroupJSONObject.h" + + +@implementation _ProductDetailJSONObject + +#pragma mark - factory + ++ (ProductDetailJSONObject *)ProductDetailWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[ProductDetailJSONObject alloc] initWithDictionary:dic withError:error]; +} + + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.type = [APIParser numberFromResponseDictionary:dic forKey:@"type" acceptNil:NO error:error]; + if (*error) { + return self; + } + self.advantage = [APIParser numberFromResponseDictionary:dic forKey:@"advantage" acceptNil:NO error:error]; + if (*error) { + return self; + } + self.teaserURL = [APIParser stringFromResponseDictionary:dic forKey:@"teaserURL" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + self.telephoneFlatrate = [APIParser stringFromResponseDictionary:dic forKey:@"telephoneFlatrate" acceptNumber:NO acceptNil:YES error:error]; + if (*error) { + return self; + } + self.includeHardware = [APIParser boolFromResponseDictionary:dic forKey:@"includeHardware" acceptNil:NO error:error]; + if (*error) { + return self; + } + NSDictionary *tmpSenderInfo = [APIParser dictionaryFromResponseDictionary:dic forKey:@"senderInfo" acceptNil:YES error:error]; + if (*error) { + return self; + } + if (tmpSenderInfo) { + self.senderInfo= [[SenderGroupJSONObject alloc] initWithDictionary:tmpSenderInfo withError:error]; + if (*error) { + return self; + } + } + self.anyProperty = [APIParser objectFromResponseDictionary:dic forKey:@"anyProperty" acceptNil:NO error:error]; + if (*error) { + return nil; + } + self.title = [APIParser objectFromResponseDictionary:dic forKey:@"title" acceptNil:NO error:error]; + if (*error) { + return nil; + } + self.download = [APIParser objectFromResponseDictionary:dic forKey:@"download" acceptNil:NO error:error]; + if (*error) { + return nil; + } + self.upload = [APIParser objectFromResponseDictionary:dic forKey:@"upload" acceptNil:NO error:error]; + if (*error) { + return nil; + } + } + return self; +} + +#pragma mark - getter + +- (NSString *)titleAsTitleString:(NSError **)error +{ + if (!self.title) return nil; + NSDictionary *newtitleDic = @{@"title" : self.title}; + NSString *tmpTitle = [APIParser stringFromResponseDictionary:newtitleDic forKey:@"title" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return nil; + } + if (tmpTitle == nil) { + return nil; + } + if (tmpTitle.length > 20) { + NSDictionary *userInfo = @{@"propertyName" : @"titleString", + @"key" : @"titleString", + @"reason" : @"max length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + if (tmpTitle.length < 10) { + NSDictionary *userInfo = @{@"propertyName" : @"titleString", + @"key" : @"titleString", + @"reason" : @"min length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + if (tmpTitle && [tmpTitle matchesRegExString:@"[a-z0-9]:10"] == NO) { + NSDictionary *userInfo = @{@"propertyName" : @"titleString", + @"key" : @"titleString", + @"reason" : @"validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + return tmpTitle; +} + +- (NSString *)titleAsString:(NSError **)error +{ + if (!self.title) return nil; + NSDictionary *newtitleDic = @{@"title" : self.title}; + NSString *tmpTitle = [APIParser stringFromResponseDictionary:newtitleDic forKey:@"title" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return nil; + } + return tmpTitle; +} + +- (NSNumber *)downloadAsNumber:(NSError **)error +{ + if (!self.download) return nil; + NSDictionary *newdownloadDic = @{@"download" : self.download}; + NSNumber *tmpDownload = [APIParser numberFromResponseDictionary:newdownloadDic forKey:@"download" acceptNil:NO error:error]; + if (*error) { + return nil; + } + return tmpDownload; +} + +- (NSString *)downloadAsString:(NSError **)error +{ + if (!self.download) return nil; + NSDictionary *newdownloadDic = @{@"download" : self.download}; + NSString *tmpDownload = [APIParser stringFromResponseDictionary:newdownloadDic forKey:@"download" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return nil; + } + return tmpDownload; +} + +- (NSNumber *)uploadAsNumber:(NSError **)error +{ + if (!self.upload) return nil; + NSDictionary *newuploadDic = @{@"upload" : self.upload}; + NSNumber *tmpUpload = [APIParser numberFromResponseDictionary:newuploadDic forKey:@"upload" acceptNil:NO error:error]; + if (*error) { + return nil; + } + return tmpUpload; +} + +- (NSString *)uploadAsString:(NSError **)error +{ + if (!self.upload) return nil; + NSDictionary *newuploadDic = @{@"upload" : self.upload}; + NSString *tmpUpload = [APIParser stringFromResponseDictionary:newuploadDic forKey:@"upload" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return nil; + } + return tmpUpload; +} + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.type forKey:@"type"]; + [coder encodeObject:self.advantage forKey:@"advantage"]; + [coder encodeObject:self.teaserURL forKey:@"teaserURL"]; + [coder encodeObject:self.telephoneFlatrate forKey:@"telephoneFlatrate"]; + [coder encodeBool:self.includeHardware forKey:@"includeHardware"]; + [coder encodeObject:self.senderInfo forKey:@"senderInfo"]; + [coder encodeObject:self.anyProperty forKey:@"anyProperty"]; + [coder encodeObject:self.title forKey:@"title"]; + [coder encodeObject:self.download forKey:@"download"]; + [coder encodeObject:self.upload forKey:@"upload"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.type = [coder decodeObjectForKey:@"type"]; + self.advantage = [coder decodeObjectForKey:@"advantage"]; + self.teaserURL = [coder decodeObjectForKey:@"teaserURL"]; + self.telephoneFlatrate = [coder decodeObjectForKey:@"telephoneFlatrate"]; + self.includeHardware = [coder decodeBoolForKey:@"includeHardware"]; + self.senderInfo = [coder decodeObjectForKey:@"senderInfo"]; + self.anyProperty = [coder decodeObjectForKey:@"anyProperty"]; + self.title = [coder decodeObjectForKey:@"title"]; + self.download = [coder decodeObjectForKey:@"download"]; + self.upload = [coder decodeObjectForKey:@"upload"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.type) { + [dic setObject:self.type forKey:@"type"]; + } + if (self.advantage) { + [dic setObject:self.advantage forKey:@"advantage"]; + } + if (self.teaserURL) { + [dic setObject:self.teaserURL forKey:@"teaserURL"]; + } + if (self.telephoneFlatrate) { + [dic setObject:self.telephoneFlatrate forKey:@"telephoneFlatrate"]; + } + if (self.includeHardware) { + [dic setObject:[NSNumber numberWithBool:self.includeHardware] forKey:@"includeHardware"]; + } + if (self.senderInfo) { + [dic setObject:[self.senderInfo propertyDictionary] forKey:@"senderInfo"]; + } + if (self.anyProperty) { + [dic setObject:self.anyProperty forKey:@"anyProperty"]; + } + if (self.title) { + [dic setObject:self.title forKey:@"title"]; + } + if (self.download) { + [dic setObject:self.download forKey:@"download"]; + } + if (self.upload) { + [dic setObject:self.upload forKey:@"upload"]; + } + return dic; +} +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/product/AbstractInterfaceFiles/_SenderGroupJSONObject.h b/test/data/product/AbstractInterfaceFiles/_SenderGroupJSONObject.h new file mode 100644 index 0000000..9563228 --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderGroupJSONObject.h @@ -0,0 +1,42 @@ +// +// _SenderGroupJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class SenderListJSONObject; +@class SenderList2JSONObject; + +@class SenderGroupJSONObject; + +@interface _SenderGroupJSONObject : NSObject + + +// the array of sender list +@property (nonatomic, strong) NSArray *digitalSenders; +// the array of sender list +@property (nonatomic, strong) NSArray *HDOptions; +// the array of sender list +@property (nonatomic, strong) NSArray *DTVHighlights; +// the array of sender list +@property (nonatomic, strong) NSArray *IPTVSenders; + ++ (SenderGroupJSONObject *)senderGroupWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; +- (SenderListJSONObject *)senderListInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (SenderList2JSONObject *)senderList2InDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSNumber *)numberInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSString *)stringInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (BOOL )booleanInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSDate *)dateInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSData *)dataInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (SenderListJSONObject *)senderListInHDOptionsAtIndex:(NSUInteger)index withError:(NSError **)error; +- (SenderList2JSONObject *)senderList2InHDOptionsAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSString *)stringInDTVHighlightsAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSString *)titleStringInDTVHighlightsAtIndex:(NSUInteger)index withError:(NSError **)error; +- (id)objectInIPTVSendersAtIndex:(NSUInteger)index withError:(NSError **)error; + +@end diff --git a/test/data/product/AbstractInterfaceFiles/_SenderGroupJSONObject.m b/test/data/product/AbstractInterfaceFiles/_SenderGroupJSONObject.m new file mode 100644 index 0000000..b86be5b --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderGroupJSONObject.m @@ -0,0 +1,313 @@ +// +// _SenderGroupJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "SenderGroupJSONObject.h" +#import "SenderListJSONObject.h" +#import "SenderList2JSONObject.h" + + + +@implementation _SenderGroupJSONObject + +#pragma mark - factory + ++ (SenderGroupJSONObject *)senderGroupWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[SenderGroupJSONObject alloc] initWithDictionary:dic withError:error]; +} + + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.digitalSenders = [APIParser arrayFromResponseDictionary:dic forKey:@"digitalSenders" acceptNil:YES error:error]; + if (*error) { + return self; + } + self.HDOptions = [APIParser arrayFromResponseDictionary:dic forKey:@"HDOptions" acceptNil:YES error:error]; + if (*error) { + return self; + } + self.DTVHighlights = [APIParser arrayFromResponseDictionary:dic forKey:@"DTVHighlights" acceptNil:YES error:error]; + if (*error) { + return self; + } + if (self.DTVHighlights.count > 6) { + NSDictionary *userInfo = @{@"propertyName" : @"DTVHighlights", + @"key" : @"DTVHighlights", + @"reason" : @"max count validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + if (self.DTVHighlights.count < 2) { + NSDictionary *userInfo = @{@"propertyName" : @"DTVHighlights", + @"key" : @"DTVHighlights", + @"reason" : @"min count validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + self.IPTVSenders = [APIParser arrayFromResponseDictionary:dic forKey:@"IPTVSenders" acceptNil:YES error:error]; + if (*error) { + return self; + } + if (self.IPTVSenders.count > 6) { + NSDictionary *userInfo = @{@"propertyName" : @"IPTVSenders", + @"key" : @"IPTVSenders", + @"reason" : @"max count validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + if (self.IPTVSenders.count < 2) { + NSDictionary *userInfo = @{@"propertyName" : @"IPTVSenders", + @"key" : @"IPTVSenders", + @"reason" : @"min count validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + } + return self; +} + +#pragma mark - getter + +- (SenderListJSONObject *)senderListInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDictionary *tmpDigitalSendersDic = [APIParser dictionaryFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + SenderListJSONObject *tmpDigitalSenders = nil; + if (tmpDigitalSendersDic == nil) { + return nil; + } + if (tmpDigitalSendersDic) { + tmpDigitalSenders= [[SenderListJSONObject alloc] initWithDictionary:tmpDigitalSendersDic withError:error]; + if (*error) { + return nil; + } + } + return tmpDigitalSenders; +} + +- (SenderList2JSONObject *)senderList2InDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDictionary *tmpDigitalSendersDic = [APIParser dictionaryFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + SenderList2JSONObject *tmpDigitalSenders = nil; + if (tmpDigitalSendersDic == nil) { + return nil; + } + if (tmpDigitalSendersDic) { + tmpDigitalSenders= [[SenderList2JSONObject alloc] initWithDictionary:tmpDigitalSendersDic withError:error]; + if (*error) { + return nil; + } + } + return tmpDigitalSenders; +} + +- (NSNumber *)numberInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSNumber *tmpDigitalSenders = [APIParser numberFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpDigitalSenders; +} + +- (NSString *)stringInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSString *tmpDigitalSenders = [APIParser stringFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpDigitalSenders; +} + +- (BOOL)booleanInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + BOOL tmpDigitalSenders = [APIParser boolFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpDigitalSenders; +} + +- (NSDate *)dateInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDate *tmpDigitalSenders = [APIParser dateWithTimeIntervalFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpDigitalSenders; +} + +- (NSData *)dataInDigitalSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSData *tmpDigitalSenders = [APIParser dataFromResponseArray:self.digitalSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpDigitalSenders; +} + +- (SenderListJSONObject *)senderListInHDOptionsAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDictionary *tmpHDOptionsDic = [APIParser dictionaryFromResponseArray:self.HDOptions atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + SenderListJSONObject *tmpHDOptions = nil; + if (tmpHDOptionsDic == nil) { + return nil; + } + if (tmpHDOptionsDic) { + tmpHDOptions= [[SenderListJSONObject alloc] initWithDictionary:tmpHDOptionsDic withError:error]; + if (*error) { + return nil; + } + } + return tmpHDOptions; +} + +- (SenderList2JSONObject *)senderList2InHDOptionsAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDictionary *tmpHDOptionsDic = [APIParser dictionaryFromResponseArray:self.HDOptions atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + SenderList2JSONObject *tmpHDOptions = nil; + if (tmpHDOptionsDic == nil) { + return nil; + } + if (tmpHDOptionsDic) { + tmpHDOptions= [[SenderList2JSONObject alloc] initWithDictionary:tmpHDOptionsDic withError:error]; + if (*error) { + return nil; + } + } + return tmpHDOptions; +} + +- (NSString *)stringInDTVHighlightsAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSString *tmpDTVHighlights = [APIParser stringFromResponseArray:self.DTVHighlights atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpDTVHighlights; +} + +- (NSString *)titleStringInDTVHighlightsAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSString *tmpDTVHighlights = [APIParser stringFromResponseArray:self.DTVHighlights atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + if (tmpDTVHighlights.length > 20) { + NSDictionary *userInfo = @{@"propertyName" : @"titleString", + @"key" : @"titleString", + @"reason" : @"max length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + if (tmpDTVHighlights.length < 10) { + NSDictionary *userInfo = @{@"propertyName" : @"titleString", + @"key" : @"titleString", + @"reason" : @"min length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + if (tmpDTVHighlights && [tmpDTVHighlights matchesRegExString:@"[a-z0-9]:10"] == NO) { + NSDictionary *userInfo = @{@"propertyName" : @"titleString", + @"key" : @"titleString", + @"reason" : @"validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kErrorDomain_parser code:kErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return nil; + } + return tmpDTVHighlights; +} + +- (id)objectInIPTVSendersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + id tmpIPTVSenders = [APIParser objectFromResponseArray:self.IPTVSenders atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpIPTVSenders; +} + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.digitalSenders forKey:@"digitalSenders"]; + [coder encodeObject:self.HDOptions forKey:@"HDOptions"]; + [coder encodeObject:self.DTVHighlights forKey:@"DTVHighlights"]; + [coder encodeObject:self.IPTVSenders forKey:@"IPTVSenders"]; +} +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.digitalSenders = [coder decodeObjectForKey:@"digitalSenders"]; + self.HDOptions = [coder decodeObjectForKey:@"HDOptions"]; + self.DTVHighlights = [coder decodeObjectForKey:@"DTVHighlights"]; + self.IPTVSenders = [coder decodeObjectForKey:@"IPTVSenders"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.digitalSenders) { + [dic setObject:self.digitalSenders forKey:@"digitalSenders"]; + } + if (self.HDOptions) { + [dic setObject:self.HDOptions forKey:@"HDOptions"]; + } + if (self.DTVHighlights) { + [dic setObject:self.DTVHighlights forKey:@"DTVHighlights"]; + } + if (self.IPTVSenders) { + [dic setObject:self.IPTVSenders forKey:@"IPTVSenders"]; + } + return dic; +} +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/product/AbstractInterfaceFiles/_SenderJSONObject.h b/test/data/product/AbstractInterfaceFiles/_SenderJSONObject.h new file mode 100644 index 0000000..1057748 --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderJSONObject.h @@ -0,0 +1,22 @@ +// +// _SenderJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class SenderJSONObject; + +@interface _SenderJSONObject : NSObject + + +@property (nonatomic, strong) NSString *senderName; +@property (nonatomic, strong) NSString *previewImageURL; + ++ (SenderJSONObject *)senderWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; + +@end + diff --git a/test/data/product/AbstractInterfaceFiles/_SenderJSONObject.m b/test/data/product/AbstractInterfaceFiles/_SenderJSONObject.m new file mode 100644 index 0000000..7a10297 --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderJSONObject.m @@ -0,0 +1,75 @@ +// +// _SenderJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "SenderJSONObject.h" + + +@implementation _SenderJSONObject + +#pragma mark - factory + ++ (SenderJSONObject *)senderWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[SenderJSONObject alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.senderName = [APIParser stringFromResponseDictionary:dic forKey:@"senderName" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + self.previewImageURL = [APIParser stringFromResponseDictionary:dic forKey:@"previewImageURL" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + } + return self; +} + +#pragma mark - getter + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.senderName forKey:@"senderName"]; + [coder encodeObject:self.previewImageURL forKey:@"previewImageURL"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.senderName = [coder decodeObjectForKey:@"senderName"]; + self.previewImageURL = [coder decodeObjectForKey:@"previewImageURL"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.senderName) { + [dic setObject:self.senderName forKey:@"senderName"]; + } + if (self.previewImageURL) { + [dic setObject:self.previewImageURL forKey:@"previewImageURL"]; + } + return dic; +} + +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/product/AbstractInterfaceFiles/_SenderList2JSONObject.h b/test/data/product/AbstractInterfaceFiles/_SenderList2JSONObject.h new file mode 100644 index 0000000..d38477e --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderList2JSONObject.h @@ -0,0 +1,21 @@ +// +// _SenderList2JSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import +#import "SenderListJSONObject.h" + +@class SenderList2JSONObject; + +@interface _SenderList2JSONObject : SenderListJSONObject + + +// the title of sender list +@property (nonatomic, strong) NSString *listSubTitle; + ++ (SenderList2JSONObject *)senderList2WithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; + +@end diff --git a/test/data/product/AbstractInterfaceFiles/_SenderList2JSONObject.m b/test/data/product/AbstractInterfaceFiles/_SenderList2JSONObject.m new file mode 100644 index 0000000..fea7fdb --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderList2JSONObject.m @@ -0,0 +1,61 @@ +// +// _SenderList2JSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "SenderList2JSONObject.h" + + +@implementation _SenderList2JSONObject + +#pragma mark - factory + ++ (SenderList2JSONObject *)senderList2WithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[SenderList2JSONObject alloc] initWithDictionary:dic withError:error]; +} + + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super initWithDictionary:dic withError:error]; + if (self) { + self.listSubTitle = [APIParser stringFromResponseDictionary:dic forKey:@"listSubTitle" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + } + return self; +} + + +#pragma mark - getter + +#pragma mark - NSCoding +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.listSubTitle forKey:@"listSubTitle"]; +} +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.listSubTitle = [coder decodeObjectForKey:@"listSubTitle"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[super propertyDictionary] mutableCopy]; + if (self.listSubTitle) { + [dic setObject:self.listSubTitle forKey:@"listSubTitle"]; + } + return dic; +} + +@end diff --git a/test/data/product/AbstractInterfaceFiles/_SenderListJSONObject.h b/test/data/product/AbstractInterfaceFiles/_SenderListJSONObject.h new file mode 100644 index 0000000..ada1fa3 --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderListJSONObject.h @@ -0,0 +1,26 @@ +// +// _SenderListJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class SenderJSONObject; + +@class SenderListJSONObject; + +@interface _SenderListJSONObject : NSObject + + +// the title of sender list +@property (nonatomic, strong) NSString *listTitle; +// the array of Sender +@property (nonatomic, strong) NSArray *senders; + ++ (SenderListJSONObject *)senderListWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; + +@end + diff --git a/test/data/product/AbstractInterfaceFiles/_SenderListJSONObject.m b/test/data/product/AbstractInterfaceFiles/_SenderListJSONObject.m new file mode 100644 index 0000000..db1d534 --- /dev/null +++ b/test/data/product/AbstractInterfaceFiles/_SenderListJSONObject.m @@ -0,0 +1,97 @@ +// +// _SenderListJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "SenderListJSONObject.h" +#import "SenderJSONObject.h" + + +@implementation _SenderListJSONObject + +#pragma mark - factory + ++ (SenderListJSONObject *)senderListWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[SenderListJSONObject alloc] initWithDictionary:dic withError:error]; +} + + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.listTitle = [APIParser stringFromResponseDictionary:dic forKey:@"listTitle" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + NSArray *tmpSendersArray = [APIParser arrayFromResponseDictionary:dic forKey:@"senders" acceptNil:NO error:error]; + if (*error) { + return self; + } + NSMutableArray *tmpSenders = [[NSMutableArray alloc] initWithCapacity:tmpSendersArray.count]; + for (NSUInteger loop = 0; loop < tmpSendersArray.count; loop++) { + NSDictionary *tmpDic = [APIParser dictionaryFromResponseArray:tmpSendersArray atIndex:loop acceptNil:NO error:error]; + if (*error) { + return self; + } + SenderJSONObject*tmpObject = nil; + if (tmpDic) { + tmpObject= [[SenderJSONObject alloc] initWithDictionary:tmpDic withError:error]; + if (*error) { + return self; + } + } + if (tmpObject) { + [tmpSenders addObject:tmpObject]; + } + } + self.senders = [NSArray arrayWithArray:tmpSenders]; + } + return self; +} + + +#pragma mark - getter + +#pragma mark - NSCoding +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.listTitle forKey:@"listTitle"]; + [coder encodeObject:self.senders forKey:@"senders"]; +} +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.listTitle = [coder decodeObjectForKey:@"listTitle"]; + self.senders = [coder decodeObjectForKey:@"senders"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.listTitle) { + [dic setObject:self.listTitle forKey:@"listTitle"]; + } + if (self.senders) { + NSMutableArray *tmpArray = [[NSMutableArray alloc] init]; + for (SenderJSONObject *tmpObj in self.senders) { + [tmpArray addObject:[tmpObj propertyDictionary]]; + } + [dic setObject:tmpArray forKey:@"senders"]; + } + return dic; +} +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/product/ProductDetailJSONObject.h b/test/data/product/ProductDetailJSONObject.h new file mode 100644 index 0000000..2d874b2 --- /dev/null +++ b/test/data/product/ProductDetailJSONObject.h @@ -0,0 +1,10 @@ +// +// ProductDetailJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_ProductDetailJSONObject.h" +@interface ProductDetailJSONObject : _ProductDetailJSONObject + +@end diff --git a/test/data/product/ProductDetailJSONObject.m b/test/data/product/ProductDetailJSONObject.m new file mode 100644 index 0000000..8be4033 --- /dev/null +++ b/test/data/product/ProductDetailJSONObject.m @@ -0,0 +1,15 @@ +// +// ProductDetailJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "ProductDetailJSONObject.h" + +@interface ProductDetailJSONObject () + +@end + +@implementation ProductDetailJSONObject + +@end diff --git a/test/data/product/SenderGroupJSONObject.h b/test/data/product/SenderGroupJSONObject.h new file mode 100644 index 0000000..554285d --- /dev/null +++ b/test/data/product/SenderGroupJSONObject.h @@ -0,0 +1,10 @@ +// +// SenderGroupJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_SenderGroupJSONObject.h" +@interface SenderGroupJSONObject : _SenderGroupJSONObject + +@end diff --git a/test/data/product/SenderGroupJSONObject.m b/test/data/product/SenderGroupJSONObject.m new file mode 100644 index 0000000..33f6d09 --- /dev/null +++ b/test/data/product/SenderGroupJSONObject.m @@ -0,0 +1,15 @@ +// +// SenderGroupJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "SenderGroupJSONObject.h" + +@interface SenderGroupJSONObject () + +@end + +@implementation SenderGroupJSONObject + +@end diff --git a/test/data/product/SenderJSONObject.h b/test/data/product/SenderJSONObject.h new file mode 100644 index 0000000..f1a8c60 --- /dev/null +++ b/test/data/product/SenderJSONObject.h @@ -0,0 +1,10 @@ +// +// SenderJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_SenderJSONObject.h" +@interface SenderJSONObject : _SenderJSONObject + +@end diff --git a/test/data/product/SenderJSONObject.m b/test/data/product/SenderJSONObject.m new file mode 100644 index 0000000..9a03a1f --- /dev/null +++ b/test/data/product/SenderJSONObject.m @@ -0,0 +1,15 @@ +// +// SenderJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "SenderJSONObject.h" + +@interface SenderJSONObject () + +@end + +@implementation SenderJSONObject + +@end diff --git a/test/data/product/SenderList2JSONObject.h b/test/data/product/SenderList2JSONObject.h new file mode 100644 index 0000000..cbca782 --- /dev/null +++ b/test/data/product/SenderList2JSONObject.h @@ -0,0 +1,10 @@ +// +// SenderList2JSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_SenderList2JSONObject.h" +@interface SenderList2JSONObject : _SenderList2JSONObject + +@end diff --git a/test/data/product/SenderList2JSONObject.m b/test/data/product/SenderList2JSONObject.m new file mode 100644 index 0000000..34ea99d --- /dev/null +++ b/test/data/product/SenderList2JSONObject.m @@ -0,0 +1,15 @@ +// +// SenderList2JSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "SenderList2JSONObject.h" + +@interface SenderList2JSONObject () + +@end + +@implementation SenderList2JSONObject + +@end diff --git a/test/data/product/SenderListJSONObject.h b/test/data/product/SenderListJSONObject.h new file mode 100644 index 0000000..e42268f --- /dev/null +++ b/test/data/product/SenderListJSONObject.h @@ -0,0 +1,10 @@ +// +// SenderListJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_SenderListJSONObject.h" +@interface SenderListJSONObject : _SenderListJSONObject + +@end diff --git a/test/data/product/SenderListJSONObject.m b/test/data/product/SenderListJSONObject.m new file mode 100644 index 0000000..fe9c8cb --- /dev/null +++ b/test/data/product/SenderListJSONObject.m @@ -0,0 +1,15 @@ +// +// SenderListJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "SenderListJSONObject.h" + +@interface SenderListJSONObject () + +@end + +@implementation SenderListJSONObject + +@end diff --git a/test/data/test_class.p b/test/data/test_class.p new file mode 100644 index 0000000..780fe61 --- /dev/null +++ b/test/data/test_class.p @@ -0,0 +1,78 @@ +(imetajson.JSONScheme +JSONScheme +p0 +(dp1 +S'type_description' +p2 +S'sender info.' +p3 +sS'type_name' +p4 +S'sender' +p5 +sS'projectPrefix' +p6 +S'S2M' +p7 +sS'base_type' +p8 +S'object' +p9 +sS'base_type_list' +p10 +(lp11 +sS'objectSuffix' +p12 +S'JSONObject' +p13 +sS'props' +p14 +(lp15 +(imetajson.JSONScheme +JSONScheme +p16 +(dp17 +S'domain' +p18 +(lp19 +S'ROOT' +p20 +ag5 +asS'required' +p21 +I1 +sg4 +S'senderName' +p22 +sg6 +g7 +sg8 +S'string' +p23 +sg10 +(lp24 +sg12 +g13 +sba(imetajson.JSONScheme +JSONScheme +p25 +(dp26 +g18 +(lp27 +g20 +ag5 +asg21 +I1 +sg4 +S'previewImageURL' +p28 +sg6 +g7 +sg8 +S'string' +p29 +sg10 +(lp30 +sg12 +g13 +sbasb. diff --git a/test/data/test_class/S2MSenderJSONObject.h b/test/data/test_class/S2MSenderJSONObject.h new file mode 100644 index 0000000..3b9b6da --- /dev/null +++ b/test/data/test_class/S2MSenderJSONObject.h @@ -0,0 +1,10 @@ +// +// S2MSenderJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_S2MSenderJSONObject.h" +@interface S2MSenderJSONObject : _S2MSenderJSONObject + +@end diff --git a/test/data/test_class/S2MSenderJSONObject.m b/test/data/test_class/S2MSenderJSONObject.m new file mode 100644 index 0000000..e3f593e --- /dev/null +++ b/test/data/test_class/S2MSenderJSONObject.m @@ -0,0 +1,15 @@ +// +// S2MSenderJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "S2MSenderJSONObject.h" + +@interface S2MSenderJSONObject () + +@end + +@implementation S2MSenderJSONObject + +@end diff --git a/test/data/test_class/_S2MSenderJSONObject.h b/test/data/test_class/_S2MSenderJSONObject.h new file mode 100644 index 0000000..4e03269 --- /dev/null +++ b/test/data/test_class/_S2MSenderJSONObject.h @@ -0,0 +1,20 @@ +// +// _S2MSenderJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class S2MSenderJSONObject; + +@interface _S2MSenderJSONObject : NSObject + +@property (nonatomic, strong) NSString *senderName; +@property (nonatomic, strong) NSString *previewImageURL; + ++ (S2MSenderJSONObject *)senderWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; + +@end diff --git a/test/data/test_class/_S2MSenderJSONObject.m b/test/data/test_class/_S2MSenderJSONObject.m new file mode 100644 index 0000000..c4a9cb5 --- /dev/null +++ b/test/data/test_class/_S2MSenderJSONObject.m @@ -0,0 +1,75 @@ +// +// _S2MSenderJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "S2MAPIParser.h" +#import "NSString+RegExValidation.h" +#import "S2MSenderJSONObject.h" + + +@implementation _S2MSenderJSONObject + +#pragma mark - factory + ++ (S2MSenderJSONObject *)senderWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[S2MSenderJSONObject alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.senderName = [S2MAPIParser stringFromResponseDictionary:dic forKey:@"senderName" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + self.previewImageURL = [S2MAPIParser stringFromResponseDictionary:dic forKey:@"previewImageURL" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + } + return self; +} + +#pragma mark - getter + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.senderName forKey:@"senderName"]; + [coder encodeObject:self.previewImageURL forKey:@"previewImageURL"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.senderName = [coder decodeObjectForKey:@"senderName"]; + self.previewImageURL = [coder decodeObjectForKey:@"previewImageURL"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.senderName) { + [dic setObject:self.senderName forKey:@"senderName"]; + } + if (self.previewImageURL) { + [dic setObject:self.previewImageURL forKey:@"previewImageURL"]; + } + return dic; +} + +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/test_json.p b/test/data/test_json.p new file mode 100644 index 0000000..833fb92 --- /dev/null +++ b/test/data/test_json.p @@ -0,0 +1,155 @@ +(imetajson.JSONScheme +JSONScheme +p0 +(dp1 +S'type_description' +p2 +S'test description of user type.' +p3 +sS'type_name' +p4 +S'user' +p5 +sS'projectPrefix' +p6 +S'FBE' +p7 +sS'base_type' +p8 +S'person' +p9 +sS'base_type_list' +p10 +(lp11 +sS'objectSuffix' +p12 +S'Suffix' +p13 +sS'props' +p14 +(lp15 +(imetajson.JSONScheme +JSONScheme +p16 +(dp17 +S'regex' +p18 +S'[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,4}' +p19 +sS'domain' +p20 +(lp21 +S'ROOT' +p22 +ag5 +asg4 +S'email' +p23 +sg6 +g7 +sg8 +S'string' +p24 +sg10 +(lp25 +sg12 +g13 +sba(imetajson.JSONScheme +JSONScheme +p26 +(dp27 +g20 +(lp28 +g22 +ag5 +asS'required' +p29 +I1 +sg4 +S'family' +p30 +sg6 +g7 +sg8 +S'array' +p31 +sg10 +(lp32 +sg12 +g13 +sS'sub_type' +p33 +(lp34 +S'person' +p35 +aS'userAddress' +p36 +aS'string' +p37 +asba(imetajson.JSONScheme +JSONScheme +p38 +(dp39 +g20 +(lp40 +g22 +ag5 +asg29 +I1 +sg4 +S'userID' +p41 +sg6 +g7 +sg8 +S'string' +p42 +sg10 +(lp43 +sg12 +g13 +sba(imetajson.JSONScheme +JSONScheme +p44 +(dp45 +g20 +(lp46 +g22 +ag5 +asg29 +I1 +sg4 +S'address' +p47 +sg6 +g7 +sg8 +S'userAddress' +p48 +sg10 +(lp49 +sg12 +g13 +sba(imetajson.JSONScheme +JSONScheme +p50 +(dp51 +g20 +(lp52 +g22 +ag5 +asg29 +I1 +sg4 +S'session' +p53 +sg6 +g7 +sg8 +S'mySession' +p54 +sg10 +(lp55 +sg12 +g13 +sbasb. diff --git a/test/data/test_string_options.p b/test/data/test_string_options.p new file mode 100644 index 0000000..370eb13 --- /dev/null +++ b/test/data/test_string_options.p @@ -0,0 +1,86 @@ +(imetajson.JSONScheme +JSONScheme +p0 +(dp1 +S'base_type_list' +p2 +(lp3 +sS'type_name' +p4 +S'login' +p5 +sS'projectPrefix' +p6 +S'S2M' +p7 +sS'base_type' +p8 +S'object' +p9 +sS'props' +p10 +(lp11 +(imetajson.JSONScheme +JSONScheme +p12 +(dp13 +S'regex' +p14 +S"[a-z0-9!#$%&'*+/=?^_`{|}~-](?:\\\\.[a-z0-9!#$%&'*/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" +p15 +sS'domain' +p16 +(lp17 +S'ROOT' +p18 +ag5 +asg4 +S'emailString' +p19 +sg6 +S'S2M' +p20 +sg8 +S'string' +p21 +sg2 +(lp22 +sS'objectSuffix' +p23 +S'JSONObject' +p24 +sba(imetajson.JSONScheme +JSONScheme +p25 +(dp26 +g16 +(lp27 +g18 +ag5 +asS'hasMinLength' +p28 +I01 +sS'minLength' +p29 +I3 +sg4 +S'password' +p30 +sg6 +g20 +sg8 +S'string' +p31 +sg2 +(lp32 +sg23 +g24 +sS'maxLength' +p33 +I12 +sS'hasMaxLength' +p34 +I01 +sbasg23 +g24 +sb. diff --git a/test/data/test_string_options/_S2MLoginJSONObject.h b/test/data/test_string_options/_S2MLoginJSONObject.h new file mode 100644 index 0000000..a441645 --- /dev/null +++ b/test/data/test_string_options/_S2MLoginJSONObject.h @@ -0,0 +1,20 @@ +// +// _S2MLoginJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class S2MLoginJSONObject; + +@interface _S2MLoginJSONObject : NSObject + +@property (nonatomic, strong) NSString *emailString; +@property (nonatomic, strong) NSString *password; + ++ (S2MLoginJSONObject *)loginWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; + +@end diff --git a/test/data/test_string_options/_S2MLoginJSONObject.m b/test/data/test_string_options/_S2MLoginJSONObject.m new file mode 100644 index 0000000..bd1d7d9 --- /dev/null +++ b/test/data/test_string_options/_S2MLoginJSONObject.m @@ -0,0 +1,105 @@ +// +// _S2MLoginJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "S2MAPIParser.h" +#import "NSString+RegExValidation.h" +#import "S2MLoginJSONObject.h" + + +@implementation _S2MLoginJSONObject + +#pragma mark - factory + ++ (S2MLoginJSONObject *)loginWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[S2MLoginJSONObject alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.emailString = [S2MAPIParser stringFromResponseDictionary:dic forKey:@"emailString" acceptNumber:NO acceptNil:YES error:error]; + if (*error) { + return self; + } + if (self.emailString && [self.emailString matchesRegExString:@"[a-z0-9!#$%&'*+/=?^_`{|}~-](?:\\.[a-z0-9!#$%&'*/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"] == NO) { + NSDictionary *userInfo = @{@"propertyName" : @"emailString", + @"key" : @"emailString", + @"reason" : @"validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kS2MErrorDomain_parser code:kS2MErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + self.password = [S2MAPIParser stringFromResponseDictionary:dic forKey:@"password" acceptNumber:NO acceptNil:YES error:error]; + if (*error) { + return self; + } + if (self.password.length > 12) { + NSDictionary *userInfo = @{@"propertyName" : @"password", + @"key" : @"password", + @"reason" : @"max length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kS2MErrorDomain_parser code:kS2MErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + if (self.password.length < 3) { + NSDictionary *userInfo = @{@"propertyName" : @"password", + @"key" : @"password", + @"reason" : @"min length validation error", + @"objectClass" : NSStringFromClass([self class]) + }; + *error = [NSError errorWithDomain:kS2MErrorDomain_parser code:kS2MErrorDomain_parser_valueIsNotValid userInfo:userInfo]; + NSLog(@"%@", *error); + return self; + } + } + return self; +} + +#pragma mark - getter + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.emailString forKey:@"emailString"]; + [coder encodeObject:self.password forKey:@"password"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.emailString = [coder decodeObjectForKey:@"emailString"]; + self.password = [coder decodeObjectForKey:@"password"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.emailString) { + [dic setObject:self.emailString forKey:@"emailString"]; + } + if (self.password) { + [dic setObject:self.password forKey:@"password"]; + } + return dic; +} + +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/test_subclass/MotherClassJSONObject.h b/test/data/test_subclass/MotherClassJSONObject.h new file mode 100644 index 0000000..cf44b24 --- /dev/null +++ b/test/data/test_subclass/MotherClassJSONObject.h @@ -0,0 +1,10 @@ +// +// MotherClassJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_MotherClassJSONObject.h" +@interface MotherClassJSONObject : _MotherClassJSONObject + +@end diff --git a/test/data/test_subclass/MotherClassJSONObject.m b/test/data/test_subclass/MotherClassJSONObject.m new file mode 100644 index 0000000..69a23ae --- /dev/null +++ b/test/data/test_subclass/MotherClassJSONObject.m @@ -0,0 +1,15 @@ +// +// MotherClassJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "MotherClassJSONObject.h" + +@interface MotherClassJSONObject () + +@end + +@implementation MotherClassJSONObject + +@end diff --git a/test/data/test_subclass/SubClassJSONObject.h b/test/data/test_subclass/SubClassJSONObject.h new file mode 100644 index 0000000..df686da --- /dev/null +++ b/test/data/test_subclass/SubClassJSONObject.h @@ -0,0 +1,10 @@ +// +// SubClassJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "_SubClassJSONObject.h" +@interface SubClassJSONObject : _SubClassJSONObject + +@end diff --git a/test/data/test_subclass/SubClassJSONObject.m b/test/data/test_subclass/SubClassJSONObject.m new file mode 100644 index 0000000..4d3af39 --- /dev/null +++ b/test/data/test_subclass/SubClassJSONObject.m @@ -0,0 +1,15 @@ +// +// SubClassJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "SubClassJSONObject.h" + +@interface SubClassJSONObject () + +@end + +@implementation SubClassJSONObject + +@end diff --git a/test/data/test_subclass/_MotherClassJSONObject.h b/test/data/test_subclass/_MotherClassJSONObject.h new file mode 100644 index 0000000..db99900 --- /dev/null +++ b/test/data/test_subclass/_MotherClassJSONObject.h @@ -0,0 +1,19 @@ +// +// _MotherClassJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class MotherClassJSONObject; + +@interface _MotherClassJSONObject : NSObject + +@property (nonatomic, strong) NSString *metaId; + ++ (MotherClassJSONObject *)motherClassWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; + +@end diff --git a/test/data/test_subclass/_MotherClassJSONObject.m b/test/data/test_subclass/_MotherClassJSONObject.m new file mode 100644 index 0000000..4361cf7 --- /dev/null +++ b/test/data/test_subclass/_MotherClassJSONObject.m @@ -0,0 +1,66 @@ +// +// _MotherClassJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "MotherClassJSONObject.h" + + +@implementation _MotherClassJSONObject + +#pragma mark - factory + ++ (MotherClassJSONObject *)motherClassWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[MotherClassJSONObject alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.metaId = [APIParser stringFromResponseDictionary:dic forKey:@"id" acceptNumber:NO acceptNil:NO error:error]; + if (*error) { + return self; + } + } + return self; +} + +#pragma mark - getter + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.metaId forKey:@"id"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.metaId = [coder decodeObjectForKey:@"id"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.metaId) { + [dic setObject:self.metaId forKey:@"id"]; + } + return dic; +} + +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/test_subclass/_SubClassJSONObject.h b/test/data/test_subclass/_SubClassJSONObject.h new file mode 100644 index 0000000..a3dde38 --- /dev/null +++ b/test/data/test_subclass/_SubClassJSONObject.h @@ -0,0 +1,19 @@ +// +// _SubClassJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import +#import "MotherClassJSONObject.h" + +@class SubClassJSONObject; + +@interface _SubClassJSONObject : MotherClassJSONObject + +@property (nonatomic, strong) NSString *name; + ++ (SubClassJSONObject *)subClassWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; + +@end diff --git a/test/data/test_subclass/_SubClassJSONObject.m b/test/data/test_subclass/_SubClassJSONObject.m new file mode 100644 index 0000000..ed00750 --- /dev/null +++ b/test/data/test_subclass/_SubClassJSONObject.m @@ -0,0 +1,62 @@ +// +// _SubClassJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "APIParser.h" +#import "NSString+RegExValidation.h" +#import "SubClassJSONObject.h" + + +@implementation _SubClassJSONObject + +#pragma mark - factory + ++ (SubClassJSONObject *)subClassWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[SubClassJSONObject alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super initWithDictionary:dic withError:error]; + if (self) { + self.name = [APIParser stringFromResponseDictionary:dic forKey:@"name" acceptNumber:NO acceptNil:YES error:error]; + if (*error) { + return self; + } + } + return self; +} + +#pragma mark - getter + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeObject:self.name forKey:@"name"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.name = [coder decodeObjectForKey:@"name"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[super propertyDictionary] mutableCopy]; + if (self.name) { + [dic setObject:self.name forKey:@"name"]; + } + return dic; +} + + +@end diff --git a/test/data/test_subclass_motherClass.p b/test/data/test_subclass_motherClass.p new file mode 100644 index 0000000..604fe98 --- /dev/null +++ b/test/data/test_subclass_motherClass.p @@ -0,0 +1,52 @@ +(imetajson.JSONScheme +JSONScheme +p0 +(dp1 +S'base_type_list' +p2 +(lp3 +sS'type_name' +p4 +S'motherClass' +p5 +sS'projectPrefix' +p6 +S'' +p7 +sS'base_type' +p8 +S'object' +p9 +sS'props' +p10 +(lp11 +(imetajson.JSONScheme +JSONScheme +p12 +(dp13 +S'domain' +p14 +(lp15 +S'ROOT' +p16 +ag5 +asS'required' +p17 +I1 +sg4 +S'id' +p18 +sg6 +g7 +sg8 +S'string' +p19 +sg2 +(lp20 +sS'objectSuffix' +p21 +S'JSONObject' +p22 +sbasg21 +g22 +sb. diff --git a/test/data/test_subclass_scheme.p b/test/data/test_subclass_scheme.p new file mode 100644 index 0000000..095ba03 --- /dev/null +++ b/test/data/test_subclass_scheme.p @@ -0,0 +1,111 @@ +(dp0 +S'ROOTmotherClass' +p1 +(dp2 +S'id' +p3 +(imetajson.JSONScheme +JSONScheme +p4 +(dp5 +S'domain' +p6 +(lp7 +S'ROOT' +p8 +aS'motherClass' +p9 +asS'required' +p10 +I1 +sS'type_name' +p11 +g3 +sS'projectPrefix' +p12 +S'' +p13 +sS'base_type' +p14 +S'string' +p15 +sS'base_type_list' +p16 +(lp17 +sS'objectSuffix' +p18 +S'JSONObject' +p19 +sbssS'ROOTsubClass' +p20 +(dp21 +S'name' +p22 +(imetajson.JSONScheme +JSONScheme +p23 +(dp24 +g6 +(lp25 +g8 +aS'subClass' +p26 +asg10 +I0 +sg11 +g22 +sg12 +g13 +sg14 +S'string' +p27 +sg16 +(lp28 +sg18 +g19 +sbssg8 +(dp29 +g9 +(imetajson.JSONScheme +JSONScheme +p30 +(dp31 +g16 +(lp32 +sg11 +g9 +sg12 +g13 +sg14 +S'object' +p33 +sS'props' +p34 +(lp35 +g4 +asg18 +g19 +sbsg26 +(imetajson.JSONScheme +JSONScheme +p36 +(dp37 +S'type_description' +p38 +S'subclass of motherClass' +p39 +sg11 +g26 +sg12 +g13 +sg14 +S'motherClass' +p40 +sg16 +(lp41 +sg18 +g19 +sg34 +(lp42 +g23 +asbss. diff --git a/test/data/test_subclass_subClass.p b/test/data/test_subclass_subClass.p new file mode 100644 index 0000000..be13ea2 --- /dev/null +++ b/test/data/test_subclass_subClass.p @@ -0,0 +1,56 @@ +(imetajson.JSONScheme +JSONScheme +p0 +(dp1 +S'type_description' +p2 +S'subclass of motherClass' +p3 +sS'type_name' +p4 +S'subClass' +p5 +sS'projectPrefix' +p6 +S'' +p7 +sS'base_type' +p8 +S'motherClass' +p9 +sS'base_type_list' +p10 +(lp11 +sS'objectSuffix' +p12 +S'JSONObject' +p13 +sS'props' +p14 +(lp15 +(imetajson.JSONScheme +JSONScheme +p16 +(dp17 +S'domain' +p18 +(lp19 +S'ROOT' +p20 +ag5 +asS'required' +p21 +I0 +sg4 +S'name' +p22 +sg6 +g7 +sg8 +S'string' +p23 +sg10 +(lp24 +sg12 +g13 +sbasb. \ No newline at end of file diff --git a/test/data/test_types/_S2MSuperObjectJSONObject.h b/test/data/test_types/_S2MSuperObjectJSONObject.h new file mode 100644 index 0000000..7c6d20a --- /dev/null +++ b/test/data/test_types/_S2MSuperObjectJSONObject.h @@ -0,0 +1,29 @@ +// +// _S2MSuperObjectJSONObject.h +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import + +@class S2MSuperObjectJSONObject; + +@interface _S2MSuperObjectJSONObject : NSObject + +@property (nonatomic, assign) BOOL isBoolean; +@property (nonatomic, strong) NSData *myData; +@property (nonatomic, strong) NSDate *creationDate; +@property (nonatomic, strong) NSArray *objectWithoutSubtypes; +@property (nonatomic, strong) NSArray *numbers; +@property (nonatomic, strong) NSArray *stringsAndDates; +@property (nonatomic, strong) NSArray *customNumbers; +@property (nonatomic, strong) NSArray *stringsAndCustomNumbers; + ++ (S2MSuperObjectJSONObject *)superObjectWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error; +- (NSDictionary *)propertyDictionary; +- (NSString *)stringInStringsAndDatesAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSDate *)dateInStringsAndDatesAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSNumber *)customNumberInStringsAndCustomNumbersAtIndex:(NSUInteger)index withError:(NSError **)error; +- (NSString *)stringInStringsAndCustomNumbersAtIndex:(NSUInteger)index withError:(NSError **)error; +@end diff --git a/test/data/test_types/_S2MSuperObjectJSONObject.m b/test/data/test_types/_S2MSuperObjectJSONObject.m new file mode 100644 index 0000000..4f70e4c --- /dev/null +++ b/test/data/test_types/_S2MSuperObjectJSONObject.m @@ -0,0 +1,187 @@ +// +// _S2MSuperObjectJSONObject.m +// +// Created by MetaJSONParser. +// Copyright (c) 2014 SinnerSchrader Mobile. All rights reserved. + +#import "S2MAPIParser.h" +#import "NSString+RegExValidation.h" +#import "S2MSuperObjectJSONObject.h" + + +@implementation _S2MSuperObjectJSONObject + +#pragma mark - factory + ++ (S2MSuperObjectJSONObject *)superObjectWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + return [[S2MSuperObjectJSONObject alloc] initWithDictionary:dic withError:error]; +} + +#pragma mark - initialize +- (id)initWithDictionary:(NSDictionary *)dic withError:(NSError **)error +{ + self = [super init]; + if (self) { + self.isBoolean = [S2MAPIParser boolFromResponseDictionary:dic forKey:@"isBoolean" acceptNil:YES error:error]; + if (*error) { + return self; + } + self.myData = [S2MAPIParser dataFromResponseDictionary:dic forKey:@"myData" acceptNil:YES error:error]; + if (*error) { + return self; + } + self.creationDate = [S2MAPIParser dateWithTimeIntervalFromResponseDictionary:dic forKey:@"creationDate" acceptNil:YES error:error]; + if (*error) { + return self; + } + self.objectWithoutSubtypes = [S2MAPIParser arrayFromResponseDictionary:dic forKey:@"objectWithoutSubtypes" acceptNil:YES error:error]; + if (*error) { + return self; + } + NSArray *tmpNumbersArray = [S2MAPIParser arrayFromResponseDictionary:dic forKey:@"numbers" acceptNil:YES error:error]; + if (*error) { + return self; + } + NSMutableArray *tmpNumbers = [[NSMutableArray alloc] initWithCapacity:tmpNumbersArray.count]; + for (NSUInteger loop = 0; loop < tmpNumbersArray.count; loop++) { + NSNumber *tmpValue = [S2MAPIParser numberFromResponseArray:tmpNumbersArray atIndex:loop acceptNil:YES error:error]; + if (*error) { + return self; + } + if (tmpValue) { + [tmpNumbers addObject:tmpValue]; + } + } + self.numbers = [NSArray arrayWithArray:tmpNumbers]; + self.stringsAndDates = [S2MAPIParser arrayFromResponseDictionary:dic forKey:@"stringsAndDates" acceptNil:YES error:error]; + if (*error) { + return self; + } + NSArray *tmpCustomNumbersArray = [S2MAPIParser arrayFromResponseDictionary:dic forKey:@"customNumbers" acceptNil:YES error:error]; + if (*error) { + return self; + } + NSMutableArray *tmpCustomNumbers = [[NSMutableArray alloc] initWithCapacity:tmpCustomNumbersArray.count]; + for (NSUInteger loop = 0; loop < tmpCustomNumbersArray.count; loop++) { + NSNumber *tmpValue = [S2MAPIParser numberFromResponseArray:tmpCustomNumbersArray atIndex:loop acceptNil:YES error:error]; + if (*error) { + return self; + } + if (tmpValue) { + [tmpCustomNumbers addObject:tmpValue]; + } + } + self.customNumbers = [NSArray arrayWithArray:tmpCustomNumbers]; + self.stringsAndCustomNumbers = [S2MAPIParser arrayFromResponseDictionary:dic forKey:@"stringsAndCustomNumbers" acceptNil:YES error:error]; + if (*error) { + return self; + } + } + return self; +} + +#pragma mark - getter + +- (NSString *)stringInStringsAndDatesAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSString *tmpStringsAndDates = [S2MAPIParser stringFromResponseArray:self.stringsAndDates atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpStringsAndDates; +} + +- (NSDate *)dateInStringsAndDatesAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSDate *tmpStringsAndDates = [S2MAPIParser dateWithTimeIntervalFromResponseArray:self.stringsAndDates atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpStringsAndDates; +} + +- (NSNumber *)customNumberInStringsAndCustomNumbersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSNumber *tmpStringsAndCustomNumbers = [S2MAPIParser numberFromResponseArray:self.stringsAndCustomNumbers atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpStringsAndCustomNumbers; +} + +- (NSString *)stringInStringsAndCustomNumbersAtIndex:(NSUInteger)index withError:(NSError **)error +{ + NSString *tmpStringsAndCustomNumbers = [S2MAPIParser stringFromResponseArray:self.stringsAndCustomNumbers atIndex:index acceptNil:YES error:error]; + if (*error) { + return nil; + } + return tmpStringsAndCustomNumbers; +} + +#pragma mark - NSCoding + +- (void)encodeWithCoder:(NSCoder*)coder +{ + [super encodeWithCoder:coder]; + [coder encodeBool:self.isBoolean forKey:@"isBoolean"]; + [coder encodeObject:self.myData forKey:@"myData"]; + [coder encodeObject:self.creationDate forKey:@"creationDate"]; + [coder encodeObject:self.objectWithoutSubtypes forKey:@"objectWithoutSubtypes"]; + [coder encodeObject:self.numbers forKey:@"numbers"]; + [coder encodeObject:self.stringsAndDates forKey:@"stringsAndDates"]; + [coder encodeObject:self.customNumbers forKey:@"customNumbers"]; + [coder encodeObject:self.stringsAndCustomNumbers forKey:@"stringsAndCustomNumbers"]; +} + +- (id)initWithCoder:(NSCoder *)coder +{ + self = [super initWithCoder:coder]; + self.isBoolean = [coder decodeBoolForKey:@"isBoolean"]; + self.myData = [coder decodeObjectForKey:@"myData"]; + self.creationDate = [coder decodeObjectForKey:@"creationDate"]; + self.objectWithoutSubtypes = [coder decodeObjectForKey:@"objectWithoutSubtypes"]; + self.numbers = [coder decodeObjectForKey:@"numbers"]; + self.stringsAndDates = [coder decodeObjectForKey:@"stringsAndDates"]; + self.customNumbers = [coder decodeObjectForKey:@"customNumbers"]; + self.stringsAndCustomNumbers = [coder decodeObjectForKey:@"stringsAndCustomNumbers"]; + return self; +} + +#pragma mark - Object Info +- (NSDictionary *)propertyDictionary +{ + NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; + if (self.isBoolean) { + [dic setObject:[NSNumber numberWithBool:self.isBoolean] forKey:@"isBoolean"]; + } + if (self.myData) { + [dic setObject:self.myData forKey:@"myData"]; + } + if (self.creationDate) { + [dic setObject:[NSNumber numberWithInteger:[[NSNumber numberWithDouble:[self.creationDate timeIntervalSince1970]] longValue]] forKey:@"creationDate"]; + } + if (self.objectWithoutSubtypes) { + [dic setObject:self.objectWithoutSubtypes forKey:@"objectWithoutSubtypes"]; + } + if (self.numbers) { + [dic setObject:self.numbers forKey:@"numbers"]; + } + if (self.stringsAndDates) { + [dic setObject:self.stringsAndDates forKey:@"stringsAndDates"]; + } + if (self.customNumbers) { + [dic setObject:self.customNumbers forKey:@"customNumbers"]; + } + if (self.stringsAndCustomNumbers) { + [dic setObject:self.stringsAndCustomNumbers forKey:@"stringsAndCustomNumbers"]; + } + return dic; +} + +- (NSString *)description +{ + return [[self propertyDictionary] description]; +} + +@end diff --git a/test/data/test_types_scheme.p b/test/data/test_types_scheme.p new file mode 100644 index 0000000..ec8e5a2 --- /dev/null +++ b/test/data/test_types_scheme.p @@ -0,0 +1,262 @@ +(dp0 +S'ROOT' +p1 +(dp2 +S'customNumber' +p3 +(imetajson.JSONScheme +JSONScheme +p4 +(dp5 +S'base_type_list' +p6 +(lp7 +sS'hasMinLength' +p8 +I01 +sS'minLength' +p9 +I1 +sS'type_name' +p10 +g3 +sS'projectPrefix' +p11 +S'S2M' +p12 +sS'base_type' +p13 +S'number' +p14 +sS'maxLength' +p15 +I10 +sS'objectSuffix' +p16 +S'JSONObject' +p17 +sS'hasMaxLength' +p18 +I01 +sbsS'superObject' +p19 +(imetajson.JSONScheme +JSONScheme +p20 +(dp21 +g6 +(lp22 +sg10 +g19 +sg11 +g12 +sg13 +S'object' +p23 +sS'props' +p24 +(lp25 +(imetajson.JSONScheme +JSONScheme +p26 +(dp27 +S'domain' +p28 +(lp29 +g1 +ag19 +asg10 +S'isBoolean' +p30 +sg11 +g12 +sg13 +S'boolean' +p31 +sg6 +(lp32 +sg16 +g17 +sba(imetajson.JSONScheme +JSONScheme +p33 +(dp34 +g28 +(lp35 +g1 +ag19 +asg10 +S'myData' +p36 +sg11 +g12 +sg13 +S'data' +p37 +sg6 +(lp38 +sg16 +g17 +sba(imetajson.JSONScheme +JSONScheme +p39 +(dp40 +g28 +(lp41 +g1 +ag19 +asg10 +S'creationDate' +p42 +sg11 +g12 +sg13 +S'date' +p43 +sg6 +(lp44 +sg16 +g17 +sba(imetajson.JSONScheme +JSONScheme +p45 +(dp46 +g28 +(lp47 +g1 +ag19 +asg10 +S'objectWithoutSubtypes' +p48 +sg11 +g12 +sg13 +S'array' +p49 +sg6 +(lp50 +sg16 +g17 +sba(imetajson.JSONScheme +JSONScheme +p51 +(dp52 +g28 +(lp53 +g1 +ag19 +asg10 +S'numbers' +p54 +sg11 +g12 +sg13 +S'array' +p55 +sg6 +(lp56 +sg16 +g17 +sS'sub_type' +p57 +(lp58 +S'number' +p59 +asba(imetajson.JSONScheme +JSONScheme +p60 +(dp61 +g28 +(lp62 +g1 +ag19 +asg10 +S'stringsAndDates' +p63 +sg11 +g12 +sg13 +S'array' +p64 +sg6 +(lp65 +sg16 +g17 +sg57 +(lp66 +S'string' +p67 +aS'date' +p68 +asba(imetajson.JSONScheme +JSONScheme +p69 +(dp70 +g28 +(lp71 +g1 +ag19 +asg10 +S'customNumbers' +p72 +sg11 +g12 +sg13 +S'array' +p73 +sg6 +(lp74 +sg16 +g17 +sg57 +(lp75 +S'customNumber' +p76 +asba(imetajson.JSONScheme +JSONScheme +p77 +(dp78 +g28 +(lp79 +g1 +ag19 +asg10 +S'stringsAndCustomNumbers' +p80 +sg11 +g12 +sg13 +S'array' +p81 +sg6 +(lp82 +sg16 +g17 +sg57 +(lp83 +S'string' +p84 +aS'customNumber' +p85 +asbasg16 +g17 +sbssS'ROOTsuperObject' +p86 +(dp87 +g30 +g26 +sg48 +g45 +sg36 +g33 +sg80 +g77 +sg72 +g69 +sg54 +g51 +sg42 +g39 +sg63 +g60 +ss. \ No newline at end of file diff --git a/test/data/test_types_superObject.p b/test/data/test_types_superObject.p new file mode 100644 index 0000000..ebad16d --- /dev/null +++ b/test/data/test_types_superObject.p @@ -0,0 +1,210 @@ +(imetajson.JSONScheme +JSONScheme +p0 +(dp1 +S'base_type_list' +p2 +(lp3 +sS'type_name' +p4 +S'superObject' +p5 +sS'projectPrefix' +p6 +S'S2M' +p7 +sS'base_type' +p8 +S'object' +p9 +sS'props' +p10 +(lp11 +(imetajson.JSONScheme +JSONScheme +p12 +(dp13 +S'domain' +p14 +(lp15 +S'ROOT' +p16 +ag5 +asg4 +S'isBoolean' +p17 +sg6 +g7 +sg8 +S'boolean' +p18 +sg2 +(lp19 +sS'objectSuffix' +p20 +S'JSONObject' +p21 +sba(imetajson.JSONScheme +JSONScheme +p22 +(dp23 +g14 +(lp24 +g16 +ag5 +asg4 +S'myData' +p25 +sg6 +g7 +sg8 +S'data' +p26 +sg2 +(lp27 +sg20 +g21 +sba(imetajson.JSONScheme +JSONScheme +p28 +(dp29 +g14 +(lp30 +g16 +ag5 +asg4 +S'creationDate' +p31 +sg6 +g7 +sg8 +S'date' +p32 +sg2 +(lp33 +sg20 +g21 +sba(imetajson.JSONScheme +JSONScheme +p34 +(dp35 +g14 +(lp36 +g16 +ag5 +asg4 +S'objectWithoutSubtypes' +p37 +sg6 +g7 +sg8 +S'array' +p38 +sg2 +(lp39 +sg20 +g21 +sba(imetajson.JSONScheme +JSONScheme +p40 +(dp41 +g14 +(lp42 +g16 +ag5 +asg4 +S'numbers' +p43 +sg6 +g7 +sg8 +S'array' +p44 +sg2 +(lp45 +sg20 +g21 +sS'sub_type' +p46 +(lp47 +S'number' +p48 +asba(imetajson.JSONScheme +JSONScheme +p49 +(dp50 +g14 +(lp51 +g16 +ag5 +asg4 +S'stringsAndDates' +p52 +sg6 +g7 +sg8 +S'array' +p53 +sg2 +(lp54 +sg20 +g21 +sg46 +(lp55 +S'string' +p56 +aS'date' +p57 +asba(imetajson.JSONScheme +JSONScheme +p58 +(dp59 +g14 +(lp60 +g16 +ag5 +asg4 +S'customNumbers' +p61 +sg6 +g7 +sg8 +S'array' +p62 +sg2 +(lp63 +sg20 +g21 +sg46 +(lp64 +S'customNumber' +p65 +asba(imetajson.JSONScheme +JSONScheme +p66 +(dp67 +g14 +(lp68 +g16 +ag5 +asg4 +S'stringsAndCustomNumbers' +p69 +sg6 +g7 +sg8 +S'array' +p70 +sg2 +(lp71 +sg20 +g21 +sg46 +(lp72 +S'string' +p73 +aS'customNumber' +p74 +asbasg20 +g21 +sb. \ No newline at end of file diff --git a/test/readJSON_test.py b/test/readJSON_test.py new file mode 100644 index 0000000..93d5748 --- /dev/null +++ b/test/readJSON_test.py @@ -0,0 +1,70 @@ +import datetime +import difflib +import os +import re +import shutil +import sys +import unittest + +class TestReadJSON(unittest.TestCase): + def setUp(self): + os.system("rm -rf ./src") + + def test_command(self): + exit_status = self.execute_script("samples/product.json", "test/data/product") + self.assertTrue(exit_status) + + def execute_script(self, json_file, output_dir): + os.system("python -m metajson -p '' -i " + json_file) + # ignoring template files + shutil.rmtree(os.path.join("src", "APIParser")) + shutil.rmtree(os.path.join("src", "Utilities")) + return self.compare_dirs("src", output_dir, fix_date = True) + + def test_yaml_input(self): + json_file = os.path.join("samples", "product.json") + yaml_file = os.path.join("samples", "product.yaml") + json_out_dir = os.path.join("src", "json") + yaml_out_dir = os.path.join("src", "yaml") + os.system("python -m metajson -i " + json_file + " -o " + json_out_dir) + os.system("python -m metajson -i " + yaml_file + " -o " + yaml_out_dir) + exit_status = self.compare_dirs(json_out_dir, yaml_out_dir) + self.assertTrue(exit_status) + + def compare_dirs(self, dir_a, dir_b, fix_date = False): + files_in_a = [] + for (dirpath, subdirs, filenames) in os.walk(dir_a): + current_dir = dirpath + for filename in filenames: + cur_file_path_a = os.path.join(dirpath,filename) + cur_file_path_b = cur_file_path_a.replace(dir_a, dir_b, 1) + if not os.path.isfile(cur_file_path_b): + print "%s not found in %s." % (current_file_path_a, dir_b) + return False + files_in_a += [cur_file_path_a] + content_a = "foo" + content_b = "bar" + cur_file_a = open(cur_file_path_a, 'r') + cur_file_b = open(cur_file_path_b, 'r') + try: + content_a = cur_file_a.read() + if fix_date: + # All timestamps in reference files should be 2014, so we need to tweak our generated files to match them. + content_a = content_a.replace(str(datetime.datetime.now().year), "2014") + content_a = re.sub("\s", "", content_a) + content_b = re.sub("\s", "", cur_file_b.read()) + finally: + cur_file_a.close() + cur_file_b.close() + if content_a != content_b: + for line in difflib.unified_diff(content_a, content_b, fromfile=cur_file_path_a, tofile=cur_file_path_b): + sys.stdout.write(line) + return False + for (dirpath, subdirs, filenames) in os.walk(dir_b): + for filename in filenames: + current_file_name = os.path.join(dirpath, filename) + if not (current_file_name.replace(dir_b, dir_a, 1) in files_in_a): + print "%s not found in %s" % (current_file_name, dir_a) + return False + return True + diff --git a/test/template_code_generator_test.py b/test/template_code_generator_test.py new file mode 100644 index 0000000..631f468 --- /dev/null +++ b/test/template_code_generator_test.py @@ -0,0 +1,36 @@ +import unittest +import os + +from metajson.template_code_generator import * + + +class TestTemplateCodeGenerator(unittest.TestCase): + def setUp(self): + self.object = TemplateCodeGenerator("./metajson/templates/iOS") + os.system("rm -rf ./classes") + + def test_read_template(self): + expected_jsons = ['./metajson/templates/iOS/_CLASSNAME_.h.mustache', './metajson/templates/iOS/_CLASSNAME_.m.mustache', './metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.h.mustache', './metajson/templates/iOS/AbstractInterfaceFiles/__CLASSNAME_.m.mustache'] + expected_api_templates = ['./metajson/templates/iOS/APIParser/_PREFIX_APIParser.h', './metajson/templates/iOS/APIParser/_PREFIX_APIParser.m', './metajson/templates/iOS/Utilities/NSString+RegExValidation.h', './metajson/templates/iOS/Utilities/NSString+RegExValidation.m'] + + self.object.read_template() + + self.assertEqual(sorted(self.object.json_template_files),sorted(expected_jsons)) + self.assertEqual(sorted(self.object.general_template_files),sorted(expected_api_templates)) + + def test_create_output_file(self): + output = "classes/APIParser/S2MAPIParser.h" + self.object.create_output_file("./metajson/templates/iOS/APIParser/_PREFIX_APIParser.h") + file_exists = os.path.isfile(output) and os.access(output, os.R_OK) + self.assertEqual(file_exists, True) + + def test_create_output_file_without_project_prefix(self): + self.object.project_prefix = "" + output = "classes/APIParser/APIParser.h" + self.object.create_output_file("./metajson/templates/iOS/APIParser/_PREFIX_APIParser.h") + file_exists = os.path.isfile(output) and os.access(output, os.R_OK) + self.assertEqual(file_exists, True) + + # Uncomment for manual testing + # def test_write_general_template_files(self): + # self.object.write_general_template_files()