| | 116 | struct _wi_p7_spec_collection { |
|---|
| | 117 | wi_runtime_base_t base; |
|---|
| | 118 | |
|---|
| | 119 | wi_string_t *name; |
|---|
| | 120 | wi_array_t *fields; |
|---|
| | 121 | }; |
|---|
| | 122 | |
|---|
| | 123 | static _wi_p7_spec_collection_t * _wi_p7_spec_collection_with_node(wi_p7_spec_t *, xmlNodePtr); |
|---|
| | 124 | static void _wi_p7_spec_collection_dealloc(wi_runtime_instance_t *); |
|---|
| | 125 | static wi_string_t * _wi_p7_spec_collection_description(wi_runtime_instance_t *); |
|---|
| | 126 | |
|---|
| | 127 | static wi_runtime_id_t _wi_p7_spec_collection_runtime_id = WI_RUNTIME_ID_NULL; |
|---|
| | 128 | static wi_runtime_class_t _wi_p7_spec_collection_runtime_class = { |
|---|
| | 129 | "_wi_p7_spec_collection_t", |
|---|
| | 130 | _wi_p7_spec_collection_dealloc, |
|---|
| | 131 | NULL, |
|---|
| | 132 | NULL, |
|---|
| | 133 | _wi_p7_spec_collection_description, |
|---|
| | 134 | NULL |
|---|
| | 135 | }; |
|---|
| | 136 | |
|---|
| | 137 | |
|---|
| | 138 | |
|---|
| 833 | | if(strcmp((const char *) field_node->name, "field") == 0) { |
|---|
| 834 | | if(!_wi_p7_spec_load_field(p7_spec, field_node)) |
|---|
| 835 | | return false; |
|---|
| 836 | | } |
|---|
| 837 | | else if(strcmp((const char *) field_node->name, "collection") == 0) { |
|---|
| 838 | | if(!_wi_p7_spec_load_collection(p7_spec, field_node)) |
|---|
| 839 | | return false; |
|---|
| 840 | | } |
|---|
| | 870 | if(strcmp((const char *) field_node->name, "field") != 0) { |
|---|
| | 871 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 872 | WI_STR("Expected \"field\" node but got \"%s\""), |
|---|
| | 873 | field_node->name); |
|---|
| | 874 | |
|---|
| | 875 | return false; |
|---|
| | 876 | } |
|---|
| | 877 | |
|---|
| | 878 | field = _wi_p7_spec_field_with_node(p7_spec, field_node); |
|---|
| | 879 | |
|---|
| | 880 | if(!field) |
|---|
| | 881 | return false; |
|---|
| | 882 | |
|---|
| | 883 | if(wi_hash_data_for_key(p7_spec->fields_name, field->name)) { |
|---|
| | 884 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 885 | WI_STR("Field with name \"%@\" already exists"), |
|---|
| | 886 | field->name); |
|---|
| | 887 | |
|---|
| | 888 | return false; |
|---|
| | 889 | } |
|---|
| | 890 | |
|---|
| | 891 | if(wi_hash_data_for_key(p7_spec->fields_id, (void *) field->id)) { |
|---|
| | 892 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 893 | WI_STR("Field with id %lu (name \"%@\") already exists"), |
|---|
| | 894 | field->id, field->name); |
|---|
| | 895 | |
|---|
| | 896 | return false; |
|---|
| | 897 | } |
|---|
| | 898 | |
|---|
| | 899 | wi_hash_set_data_for_key(p7_spec->fields_name, field, field->name); |
|---|
| | 900 | wi_hash_set_data_for_key(p7_spec->fields_id, field, (void *) field->id); |
|---|
| 849 | | static wi_boolean_t _wi_p7_spec_load_collection(wi_p7_spec_t *p7_spec, xmlNodePtr node) { |
|---|
| 850 | | wi_array_t *collection; |
|---|
| 851 | | wi_string_t *name; |
|---|
| 852 | | _wi_p7_spec_field_t *field; |
|---|
| 853 | | xmlNodePtr field_node; |
|---|
| 854 | | |
|---|
| 855 | | name = wi_autorelease(wi_p7_xml_copy_string_for_attribute(node, WI_STR("name"))); |
|---|
| 856 | | |
|---|
| 857 | | if(!name) { |
|---|
| 858 | | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| 859 | | WI_STR("Collection has no \"name\"")); |
|---|
| 860 | | |
|---|
| 861 | | return false; |
|---|
| 862 | | } |
|---|
| 863 | | |
|---|
| 864 | | if(wi_hash_data_for_key(p7_spec->collections_name, name)) { |
|---|
| 865 | | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| 866 | | WI_STR("Collection with name \"%@\" already exists"), |
|---|
| 867 | | name); |
|---|
| 868 | | |
|---|
| 869 | | return false; |
|---|
| 870 | | } |
|---|
| 871 | | |
|---|
| 872 | | collection = wi_array(); |
|---|
| 873 | | |
|---|
| 874 | | for(field_node = node->children; field_node != NULL; field_node = field_node->next) { |
|---|
| 875 | | if(field_node->type == XML_ELEMENT_NODE) { |
|---|
| 876 | | field = _wi_p7_spec_load_field(p7_spec, field_node); |
|---|
| 877 | | |
|---|
| 878 | | if(!field) |
|---|
| 879 | | return false; |
|---|
| 880 | | |
|---|
| 881 | | wi_array_add_data(collection, field); |
|---|
| 882 | | } |
|---|
| 883 | | } |
|---|
| 884 | | |
|---|
| 885 | | if(wi_array_count(collection) == 0) { |
|---|
| 886 | | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| 887 | | WI_STR("Collection has no fields")); |
|---|
| 888 | | |
|---|
| 889 | | return false; |
|---|
| 890 | | } |
|---|
| 891 | | |
|---|
| 892 | | wi_hash_set_data_for_key(p7_spec->collections_name, collection, name); |
|---|
| | 909 | static wi_boolean_t _wi_p7_spec_load_collections(wi_p7_spec_t *p7_spec, xmlNodePtr node) { |
|---|
| | 910 | _wi_p7_spec_collection_t *collection; |
|---|
| | 911 | xmlNodePtr collection_node; |
|---|
| | 912 | |
|---|
| | 913 | for(collection_node = node->children; collection_node != NULL; collection_node = collection_node->next) { |
|---|
| | 914 | if(collection_node->type == XML_ELEMENT_NODE) { |
|---|
| | 915 | if(strcmp((const char *) collection_node->name, "collection") != 0) { |
|---|
| | 916 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 917 | WI_STR("Expected \"collection\" node but got \"%s\""), |
|---|
| | 918 | collection_node->name); |
|---|
| | 919 | |
|---|
| | 920 | return false; |
|---|
| | 921 | } |
|---|
| | 922 | |
|---|
| | 923 | collection = _wi_p7_spec_collection_with_node(p7_spec, collection_node); |
|---|
| | 924 | |
|---|
| | 925 | if(!collection) |
|---|
| | 926 | return false; |
|---|
| | 927 | |
|---|
| | 928 | if(wi_hash_data_for_key(p7_spec->collections_name, collection->name)) { |
|---|
| | 929 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 930 | WI_STR("Collection with name \"%@\" already exists"), |
|---|
| | 931 | collection->name); |
|---|
| | 932 | |
|---|
| | 933 | return false; |
|---|
| | 934 | } |
|---|
| | 935 | |
|---|
| | 936 | wi_hash_set_data_for_key(p7_spec->collections_name, collection, collection->name); |
|---|
| | 937 | } |
|---|
| | 938 | } |
|---|
| 895 | | } |
|---|
| 896 | | |
|---|
| 897 | | |
|---|
| 898 | | |
|---|
| 899 | | static _wi_p7_spec_field_t * _wi_p7_spec_load_field(wi_p7_spec_t *p7_spec, xmlNodePtr node) { |
|---|
| 900 | | _wi_p7_spec_field_t *field; |
|---|
| 901 | | |
|---|
| 902 | | field = _wi_p7_spec_field_with_node(p7_spec, node); |
|---|
| 903 | | |
|---|
| 904 | | if(!field) |
|---|
| 905 | | return NULL; |
|---|
| 906 | | |
|---|
| 907 | | if(wi_hash_data_for_key(p7_spec->fields_name, field->name)) { |
|---|
| 908 | | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| 909 | | WI_STR("Field with name \"%@\" already exists"), |
|---|
| 910 | | field->name); |
|---|
| 911 | | |
|---|
| 912 | | return NULL; |
|---|
| 913 | | } |
|---|
| 914 | | |
|---|
| 915 | | if(wi_hash_data_for_key(p7_spec->fields_id, (void *) field->id)) { |
|---|
| 916 | | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| 917 | | WI_STR("Field with id %lu (name \"%@\") already exists"), |
|---|
| 918 | | field->id, field->name); |
|---|
| 919 | | |
|---|
| 920 | | return NULL; |
|---|
| 921 | | } |
|---|
| 922 | | |
|---|
| 923 | | wi_hash_set_data_for_key(p7_spec->fields_name, field, field->name); |
|---|
| 924 | | wi_hash_set_data_for_key(p7_spec->fields_id, field, (void *) field->id); |
|---|
| 925 | | |
|---|
| 926 | | return field; |
|---|
| | 1906 | static _wi_p7_spec_collection_t * _wi_p7_spec_collection_with_node(wi_p7_spec_t *p7_spec, xmlNodePtr node) { |
|---|
| | 1907 | xmlNodePtr member_node; |
|---|
| | 1908 | _wi_p7_spec_collection_t *collection; |
|---|
| | 1909 | _wi_p7_spec_field_t *field; |
|---|
| | 1910 | wi_string_t *field_name; |
|---|
| | 1911 | |
|---|
| | 1912 | collection = wi_autorelease(wi_runtime_create_instance(_wi_p7_spec_collection_runtime_id, sizeof(_wi_p7_spec_collection_t))); |
|---|
| | 1913 | collection->name = wi_p7_xml_copy_string_for_attribute(node, WI_STR("name")); |
|---|
| | 1914 | |
|---|
| | 1915 | if(!collection->name) { |
|---|
| | 1916 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 1917 | WI_STR("Collection has no \"name\"")); |
|---|
| | 1918 | |
|---|
| | 1919 | return NULL; |
|---|
| | 1920 | } |
|---|
| | 1921 | |
|---|
| | 1922 | collection->fields = wi_array_init(wi_array_alloc()); |
|---|
| | 1923 | |
|---|
| | 1924 | for(member_node = node->children; member_node != NULL; member_node = member_node->next) { |
|---|
| | 1925 | if(member_node->type == XML_ELEMENT_NODE) { |
|---|
| | 1926 | if(strcmp((const char *) member_node->name, "member") != 0) { |
|---|
| | 1927 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 1928 | WI_STR("Expected \"member\" node but got \"%s\""), |
|---|
| | 1929 | member_node->name); |
|---|
| | 1930 | |
|---|
| | 1931 | return false; |
|---|
| | 1932 | } |
|---|
| | 1933 | |
|---|
| | 1934 | field_name = wi_autorelease(wi_p7_xml_copy_string_for_attribute(member_node, WI_STR("field"))); |
|---|
| | 1935 | |
|---|
| | 1936 | if(!field_name) { |
|---|
| | 1937 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 1938 | WI_STR("Member in collection \"%@\" has no \"field\""), |
|---|
| | 1939 | collection->name); |
|---|
| | 1940 | |
|---|
| | 1941 | return NULL; |
|---|
| | 1942 | } |
|---|
| | 1943 | |
|---|
| | 1944 | field = wi_hash_data_for_key(p7_spec->fields_name, field_name); |
|---|
| | 1945 | |
|---|
| | 1946 | if(!field && _wi_p7_spec_builtin_spec) |
|---|
| | 1947 | field = wi_hash_data_for_key(_wi_p7_spec_builtin_spec->fields_name, field_name); |
|---|
| | 1948 | |
|---|
| | 1949 | if(!field) { |
|---|
| | 1950 | wi_error_set_libwired_p7_error(WI_ERROR_P7_INVALIDSPEC, |
|---|
| | 1951 | WI_STR("Member in collection \"%@\" has an invalid \"field\" (\"%@\")"), |
|---|
| | 1952 | collection->name, field_name); |
|---|
| | 1953 | |
|---|
| | 1954 | return NULL; |
|---|
| | 1955 | } |
|---|
| | 1956 | |
|---|
| | 1957 | wi_array_add_data(collection->fields, field); |
|---|
| | 1958 | } |
|---|
| | 1959 | } |
|---|
| | 1960 | |
|---|
| | 1961 | return collection; |
|---|
| | 1962 | } |
|---|
| | 1963 | |
|---|
| | 1964 | |
|---|
| | 1965 | |
|---|
| | 1966 | static void _wi_p7_spec_collection_dealloc(wi_runtime_instance_t *instance) { |
|---|
| | 1967 | _wi_p7_spec_collection_t *collection = instance; |
|---|
| | 1968 | |
|---|
| | 1969 | wi_release(collection->name); |
|---|
| | 1970 | wi_release(collection->fields); |
|---|
| | 1971 | } |
|---|
| | 1972 | |
|---|
| | 1973 | |
|---|
| | 1974 | |
|---|
| | 1975 | static wi_string_t * _wi_p7_spec_collection_description(wi_runtime_instance_t *instance) { |
|---|
| | 1976 | _wi_p7_spec_collection_t *collection = instance; |
|---|
| | 1977 | |
|---|
| | 1978 | return wi_string_with_format(WI_STR("<%@ %p>{name = %@, fields = %@}"), |
|---|
| | 1979 | wi_runtime_class_name(collection), |
|---|
| | 1980 | collection, |
|---|
| | 1981 | collection->name, |
|---|
| | 1982 | collection->fields); |
|---|
| | 1983 | } |
|---|
| | 1984 | |
|---|
| | 1985 | |
|---|
| | 1986 | |
|---|
| | 1987 | #pragma mark - |
|---|
| | 1988 | |
|---|