{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "CityJSON v0.1",
  "description": "CityJSON specifications v0.1",
  "type": "object",

  "definitions": {
    
    "Building": {
      "type": "object",
      "properties": {
        "type": { "enum": ["Building"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"},
            "measuredHeight": { "type": "number"},
            "roofType": { "type": "string"},
            "storeysAboveGround": { "type": "integer"},
            "storeysBelowGround": { "type": "integer"},
            "storeysHeightsAboveGround": { "type": "integer"},
            "storeysHeightsBelowGround": { "type": "integer"},
            "yearOfConstruction": { "type": "integer"},
            "yearOfDemoltion": { "type": "integer"},
            "address": {}
          }
        },
        "address": {
          "type": "object",
          "properties": {
            "CountryName": {"type": "string"},
            "LocalityName": {"type": "string"},
            "ThoroughfareNumber": {"type": "string"},
            "ThoroughfareName": {"type": "string"},
            "PostalCode": {"type": "string"},
            "location": {"$ref": "#/definitions/MultiPoint"}
          }
        },
        "Parts": {
          "type": "array",
          "description": "the IDs of the BuildingPart of this Building",
          "items": {"type": "string"}
        },
        "Installations": {
          "type": "array",
          "description": "the IDs of the BuildingInstallation of this Building",
          "items": {"type": "string"}
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/CompositeSolid"},
              {"$ref": "#/definitions/MultiSurface"}
            ] 
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "BuildingPart": {
      "type": "object",
      "properties": {
        "type": { "enum": ["BuildingPart"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"},
            "measuredHeight": { "type": "number"},
            "roofType": { "type": "string"},
            "storeysAboveGround": { "type": "integer"},
            "storeysBelowGround": { "type": "integer"},
            "storeysHeightsAboveGround": { "type": "integer"},
            "storeysHeightsBelowGround": { "type": "integer"},
            "yearOfConstruction": { "type": "integer"},
            "yearOfDemoltion": { "type": "integer"},
            "address": {}
          }
        },
        "address": {
          "type": "object",
          "properties": {
            "CountryName": {"type": "string"},
            "LocalityName": {"type": "string"},
            "ThoroughfareNumber": {"type": "string"},
            "ThoroughfareName": {"type": "string"},
            "PostalCode": {"type": "string"},
            "location": {"$ref": "#/definitions/MultiPoint"}
          },
          "additionalProperties": false
        },              
        "Installations": {
          "type": "array",
            "items": {"type": "string"}
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/CompositeSolid"},
              {"$ref": "#/definitions/MultiSurface"}
            ] 
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "BuildingInstallation": {
      "type": "object",
      "properties": {
        "type": { "enum": ["BuildingInstallation"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},            
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiPoint"},
              {"$ref": "#/definitions/MultiLineString"},
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/MultiSolid"},
              {"$ref": "#/definitions/CompositeSolid"},
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/CompositeSurface"}            
            ] 
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "TINRelief": {
      "type": "object",
      "properties": {
        "type": { "enum": ["TINRelief"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"}
          }
        },        
        "geometry": {
          "type": "array",
          "items": {"$ref": "#/definitions/CompositeSurface"}
        }
      },
      "required": ["type", "geometry"]
    },

    "WaterBody": {
      "type": "object",
      "properties": {
        "type": { "enum": ["WaterBody"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},                        
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiLineString"},
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/CompositeSurface"},
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/CompositeSolid"}
            ]
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "PlantCover": {
      "type": "object",
      "properties": {
        "type": { "enum": ["PlantCover"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},                        
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"},
            "averageHeight": {"type": "number"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/MultiSolid"}
            ]
          }
        }
      },
      "required": ["type", "geometry"]
    },    

    "SolitaryVegetationObject": {
      "type": "object",
      "properties": {
        "type": { "enum": ["SolitaryVegetationObject"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},                        
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"},
            "species": {"type": "string"},
            "trunkDiameter": {"type": "number"},
            "crownDiameter": {"type": "number"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiPoint"},
              {"$ref": "#/definitions/MultiLineString"},
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/MultiSolid"},
              {"$ref": "#/definitions/CompositeSolid"},
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/CompositeSurface"}
            ]
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "LandUse": {
      "type": "object",
      "properties": {
        "type": { "enum": ["LandUse"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},                        
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/CompositeSurface"}
            ]
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "CityFurniture": {
      "type": "object",
      "properties": {
        "type": { "enum": ["CityFurniture"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},            
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiPoint"},
              {"$ref": "#/definitions/MultiLineString"},
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/MultiSolid"},
              {"$ref": "#/definitions/CompositeSolid"},
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/CompositeSurface"}
            ]
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "GenericCityObject": {
      "type": "object",
      "properties": {
        "type": { "enum": ["GenericCityObject"] },
        "attributes": {
          "type": "object",
          "properties": {
            "creationDate" : {"type": "string"},
            "terminationDate" : {"type": "string"},            
            "class": {"type": "string"},
            "function": {"type": "string"},
            "usage": {"type": "string"}
          }
        },
        "geometry": {
          "type": "array",
          "items": {
            "oneOf": [
              {"$ref": "#/definitions/MultiPoint"},
              {"$ref": "#/definitions/MultiLineString"},
              {"$ref": "#/definitions/Solid"},
              {"$ref": "#/definitions/MultiSolid"},
              {"$ref": "#/definitions/CompositeSolid"},
              {"$ref": "#/definitions/MultiSurface"},
              {"$ref": "#/definitions/CompositeSurface"}
            ]
          }
        }
      },
      "required": ["type", "geometry"]
    },

    "Solid": {
      "type": "object",
      "properties": {
        "type": { "enum": ["Solid"] },
        "lod": {"type": "number"},
        "boundaries": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "array",
                "items": {"type": "integer"}
              }
            }
          }
        },
        "semantics": {},
        "material": {},
        "texture": {}
      },
      "required": ["type", "lod", "boundaries"]
    },

    "MultiSolid": {
      "type": "object",
      "properties": {
        "type": { "enum": ["MultiSolid"] },
        "lod": {"type": "number"},
        "boundaries": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {"type": "integer"}
                }
              }
            }
          }
        }
      },
      "required": ["type", "lod", "boundaries"]
    },

    "CompositeSolid": {
      "type": "object",
      "properties": {
        "type": { "enum": ["CompositeSolid"] },
        "lod": {"type": "number"},
        "boundaries": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "array",
                "items": {
                  "type": "array",
                  "items": {"type": "integer"}
                }
              }
            }
          }
        }
      },
      "required": ["type", "lod", "boundaries"]
    },

    "MultiSurface": {
      "type": "object",
      "properties": {
        "type": { "enum": ["MultiSurface"] },
        "lod": {"type": "number"},
        "boundaries": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "array",
                "items": {"type": "integer"}
            }
          }
        },
        "semantics": {},
        "material": {},
        "texture": {}        
      },
      "required": ["type", "lod", "boundaries"]
    },

    "CompositeSurface": {
      "type": "object",
      "properties": {
        "type": { "enum": ["CompositeSurface"] },
        "lod": {"type": "number"},
        "boundaries": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": "array",
                "items": {"type": "integer"}
            }
          }
        }
      },        
    "required": ["type", "lod", "boundaries"]
    },

    "MultiLineString": {
      "type": "object",
      "properties": {
        "type": { "enum": ["MultiLineString"] },
        "lod": {"type": "number"},
        "boundaries": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {"type": "integer"}
          }
        }
      },        
      "required": ["type", "lod", "boundaries"]
    },

    "MultiPoint": {
      "type": "object",
      "properties": {
        "type": { "enum": ["MultiPoint"] },
        "lod": {"type": "number"},
        "boundaries": {
           "type": "array",
           "items": {"type": "integer"}
        }
      },
      "required": ["type", "lod", "boundaries"]
    },

    "Material": {
      "type": "object",
      "properties": {
        "name" : {"type": "string"},
        "ambient": {
          "type": "array",
          "items": {"type": "number"},
          "minItems": 3,    
          "maxItems": 3
        },
        "diffuse": {
          "type": "array",
          "items": {"type": "number"},
          "minItems": 3,    
          "maxItems": 3          
        },
        "specular": {
          "type": "array",
          "items": {"type": "number"},
          "minItems": 3,    
          "maxItems": 3
        },
        "specular-exponent": {"type": "number"},
        "illumination": {"type": "integer"},
        "transparency": {"type": "number"}
      },
      "required": ["name"]
    },

    "Texture": {
      "type": "object",
      "properties": {
        "type": { "enum": ["PNG", "JPG"] },
        "image": {"type": "string"}
      }
    }
  },

  "properties": {
    "type": {
      "description": "The type of JSON must be CityModel",
      "enum": ["CityModel"]
    },
    "version": {
      "type": "string"
    },
    "metadata": {
      "type": "object",
      "properties": {
        "crs": {
          "type": "object",
          "properties": {
            "epsg": {"type": "integer"}
          },
          "required": ["epsg"]
        },
        "bbox": {
          "type": "array",
          "items": {
            "type": "number"
          },
          "minItems": 6,    
          "maxItems": 6    
        },
        "cityjson-version": {"type": "string"},
        "keywords": {
          "type": "array",
          "items": {"type": "string"}
        },        
        "title": {"type": "string"},
        "abstract": {"type": "string"},
        "dataUrl": {"type": "string"},
        "metadataUrl": {"type": "string"},
        "dateOfCreation": {"type": "string"},
        "dateOfLastRevision": {"type": "string"},
        "dateOfPublication": {"type": "string"},
        "copyright": {"type": "string"}
      }
    },
    "CityObjects": {
      "type": "object",
      "additionalProperties": {
        "oneOf": [
          { "$ref": "#/definitions/Building" },
          { "$ref": "#/definitions/BuildingPart" },
          { "$ref": "#/definitions/BuildingInstallation" },
          { "$ref": "#/definitions/TINRelief" },
          { "$ref": "#/definitions/WaterBody" },
          { "$ref": "#/definitions/LandUse" },
          { "$ref": "#/definitions/GenericCityObject" },
          { "$ref": "#/definitions/CityFurniture" },
          { "$ref": "#/definitions/SolitaryVegetationObject" },
          { "$ref": "#/definitions/PlantCover" }
        ]
      }
    },
    "vertices": {
      "type": "array",
      "items": {
        "type": "array",
        "items": {"type": "number"},
        "minItems": 3,    
        "maxItems": 3
      }
    },
    "transform": {
      "type": "object",
      "properties": {
        "scale": {
          "type": "array",
          "items": {"type": "number"},
          "minItems": 3,    
          "maxItems": 3
        },
        "translate": {
          "type": "array",
          "items": {"type": "number"},
          "minItems": 3,    
          "maxItems": 3
        }
      },
      "required": ["scale", "translate"],
      "additionalProperties": false
    },
    "appearance": {
      "type": "object",
      "properties": {
        "materials": {
          "type": "array",
          "items": {"$ref": "#/definitions/Material"}
        },
        "textures": {
          "type": "array",
          "items": {"$ref": "#/definitions/Texture"}
        },
        "vertices-texture": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {"type": "number"},
            "minItems": 2,    
            "maxItems": 2
          }
        }
      }
    }
  },
  "required": ["type", "version", "CityObjects", "vertices"],
  "additionalProperties": false
}

