Merged DEV to HEAD

109455: Merged modules/custommodelmanagement/HEAD to DEV.
		93923: SHA-300: Added ALFRESCO_MODEL_ADMINISTRATORS group.
		95982: SHA-401: Implemented repo service for retrieving Custom Models. (WIP)
		95983: SHA-400: Added Private REST API to retrieve custom model(s)
			- Get All models: http://localhost:8080/alfresco/api/-default-/private/alfresco/versions/1/cmm
			- Get the model: http://localhost:8080/alfresco/api/-default-/private/alfresco/versions/1/cmm/<model-name>
		95984: SHA-401: Fixed the service to return null rather than throwing an exception, when the model does not exist.
		96053: SHA-400: Modified the custom model API response to return the "status" as "ACTIVE" or "DRAFT".
		96775: SHA-542: Added support to create a custom model. (WIP)
		96779: SHA-543: Added Private REST API to create custom model(s).
			- SHA-539: Cleaned up test data.
		96850: SHA-543: Added Author and Description properties to the custom model API.
		97410: SHA-407, SHA-555: Added tests for custom model backend service and the related REST API. Also, a minor modification as a result of added tests.
		97570: Modified the CMM REST API, per Kevin's request, to return empty arrays for model's types and aspects if they don't exist.
		97731: SHA-386: Added support to activate custom models. Also, a minor modification to the backend service and REST API, based on the Alfresco REST API guidelines.
		97775: SHA-386: Added tests for custom model activation (backend service). As well as, fixed the build failure by refactoring the public API tests.
		97992: SHA-573, SHA-393, SHA-494: Added support to deactivate custom model, create a new type and create a new property group (aspect).
		97994: Fixed the test as a result of renaming the service method.
		98123: SHA-393, SHA-494: Enabled the CMM REST API to create/update Types and/or Aspects via PUT. Also added validations for aspect/type's name.
		98259: SHA-453: Added backend and REST API support to delete a custom model.
		98690: SHA-393, SHA-494, SHA-453, SHA-575: Added tests for custom model backend service and the related REST API. Also, a minor modification as a result of added tests.
		99276: SHA-549: Added backend support to update a custom model. Also, refactored the service to externalise the error messages.
			- SHA-550: Added REST API support to update a custom model.
			- SHA-619: Made sure the backend service validates the model before creating a node. 
			- SHA-623: Added checks to not allow a user to create a custom model with the same name as the bootstrapped models.
		99287: SHA-619: Added InvalidCustomModelException for the CMM service to throw when the model validation fails.
		99514: SHA-506: added backend and API support to create custom Type/Aspect properties. Also refactored the API to overcome the Public API limitations.
		99522: SHA-506: Modified the Type/Aspect JSON payload to include a new read only property "prefixedName".
		99527: Fixed Bamboo build failure as the result of r99522 commit.
		99630: SHA-506: - Updated the API to exclude the inherited properties.
			- Added API tests for creating properties.
			- Modified the Custom Properties JSON response to include a new read only attribute "prefixedName".
                99662: SHA-351: Updated the API to support 'mandatory' and 'mandatoryEnforced' properties.
			- SHA-410: Updated the API to support 'defaultValue' property.
			- SHA-506: Modified the Custom Properties JSON response to include 'description' and 'multiValued' attributes.
		99669: SHA-506: Removed the unnecessary (at least in this sprint) methods from the backend service.
		99684: SHA-638: Added checks to not allow a user to create a custom model with already in-use namespace prefix.
		99959: SHA-679: Modified the custom model API to not import the already defined namespace.
		100211: SHA-607: Modified the custom model API to support delete model's type. Also, removed the unnecessary test as we depend on the dictionary service, so no need to test it in the custom model API.
		100281: Added Types and Aspects to the GET a single model API response, when it is requested with "?select=all" query string.
		100335: Added test for "?select=all" query string within the GET a single model API (see rev 100281).
		100366: SHA-612: Modified the custom model API to support delete model's aspect.
		100738: SHA-698: Added checks so the model Admin is not allowed to deactivate a custom model when its types/aspects are parent to other models' types/aspects (regardless of the model being active or not).
		100740: SHA-698: Fixed Bamboo build failures.
		101085: SHA-703: Added dependency validation before deleting custom type/aspect in the custom model API.
		101160: Modified the custom model API to return all properties (including the inherited properties) of the type/aspect, when requested by "?select=allProps".
		101636: SHA-697.
		101771: SHA-706: Made custom models hidden in the data dictionary.
		101863: SHA-701: Added checks to not allow creating duplicate properties within the same model. Also, removed unnecessary/duplicate constants from the custom model service class.
		101983: SHA-688: Fixed the error message by getting the root-cause-exception and returning its message. However, DictionaryException messages are not localised, so this will be fixed in the alfresco core.
		102223: Fix for SHA-726: Not able to edit prefix field of deactivated model when model type is referenced within same model - The API will update the parent prefixed name with the new prefix.
			- Also, added more validations to the CMM API, when setting a type/asptect's parent.
		102587: SHA-741, SHA-745, SHA-747: Added custom model Constraints support.
		102725: SHA-784: Fixed parent validation of the type/aspect.
		103030: SHA-741, SHA-745, SHA-747: Added tests for custom model Constraints.
			- Also fixed and refactored the API code as the result of tests.
		103753: SHA-846: Added inline constraints support. Also:
			- Modified the backend CMM service to throw CustomModelConstraintException when the root cause is DuplicateDefinitionException.
			- Removed the duplicate name check from the CMM API, as now it will depend on the exceptions thrown upon model compilation.
		103885: SHA-819, SHA-833: Added support to edit existing type/aspect.
		103973: SHA-819, SHA-833: Added API tests for types/aspects Edit. Also, refactored CMM API tests by moving the tests to their corresponding test class.
		104079: SHA-808: Fixed custom models bidirectional dependency.
		104158: Deleted the ExtendedRepoAdminService class as the required functionality has been added (see SHA-879) to the core alfresco code.
		104287: SHA-843: Modified the custom model API to support delete property. Also, minor refactoring of the API tests.
		104403: SHA-842: Modified the custom model API to support Edit property.
		104475: SHA-842: Added API tests for Edit property.
		104569: SHA-913 - Remove case sensitive option from the UI
			- SHA-914 - Update PO and tests that use the case sensitive option
			- Remove case sensitive option on LIST constraint throughout
			Also:
			- Update Aikau version to 1.0.18
		104690: Fixed Bamboo build failure caused by r104569.
		104849: SHA-808: Fixed custom models circular dependencies.
		105297: SHA-807: Added property default-value and constraint (REGEX, MINMAX and LENGTH) validators.
		105642: SHA-950: Wrapped backend CMM service method with a NEW transaction, in order to catch the thrown exception within DictionaryModelTypeTransactionListener. Also refactored the CMM backend service tests as the result of this change.
		106677: SHA-888, SHA-889, SHA-890: Added Backend and API support to export a custom model and its associated Share form.
		106722: SHA-888, SHA-889, SHA-890: Fixed a few minor issues raised during code review.
		107007: ACE-4019: Modified the CMM service to not start a new TX when creating a new model.
		107070: Temporarily enabled (hard coded) index and facetable attributes in the custom model properties.
		107296: GERMAN: Model Manager files localised as per EN-rev105921
		107297: FRENCH: Model Manager localised files based on EN-rev105921
		107315: SPANISH: Model Manager localised files based on EN-rev105921
		107317: JAPANESE: Model Manager localised files based on EN-rev105921
		107321: ITALIAN: Model Manager localised files based on EN-rev105921
		107322: DUTCH: Model Manager localised files based on EN-rev105921
		107335: SHA-889: Modified the CMM service to not throw an exception when exporting the model and its associated share extension module, where the Share extension module has not been created for the model yet.
		107456: SHA-893: Added API support to upload/import a custom model and its associated Share extension module.
		107560: SHA-893: Added model upload API tests as well as minor fixes.
		107647: SHA-893: Fixed minor issues raised during code review.
		107773: Docs review of message labels and errors.
		107866: SHA-1126: Added check for the maximum value of the MINMAX constraint to be a positive nonzero value.
		108117: SHA-832: Added validation for properties' default values to be checked against the property defined constraint.
		108256: SHA-1194: Modified CMM API to support indexing options.
		108510: SHA-1151: Externalised CMM rest API error messages.
			- SHA-1196: Changed the CMM Rest API input validator to use the same RegExs as the CMM Share.
		108518: SHA-1194: Changed CMM property facetable options to include "UNSET".
		108561: GERMAN: Model Manager files updated as per EN-rev107962
		108562: FRENCH: Model Manager files updated as per EN-rev107962
		108565: ITALIAN: Model Manager files updated as per EN-rev107962
		108566: SPANISH: Model Manager files updated as per EN-rev107962
		108567: JAPANESE: Model Manager files updated as per EN-rev107962
		108568: NORWEGIAN Bokmal: Model Manager files updated as per EN-rev107962
		108570: DUTCH: Model Manager files updated as per EN-rev107962
		108571: RUSSIAN: Model Manager files updated as per EN-rev107962
		108572: BRAZILIAN Portuguese: Model Manager files updated as per EN-rev107962
		108573: SIMPLIFIED CHINESE: Model Manager files updated as per EN-rev107962
		108604: Removed the unnecessary escaped quotation from the strings which don't have variables.
		108721: Api message changes from docs.
		108728: Changed "Property group" to "Aspect" in the CMM API error messages.
		108934: Added the missing escaped quotation into API messages.
		109037: Changes from docs for mandatory field character messages in the API.
		109204: ITALIAN: Updated bundle based on EN rev109039
		109205: GERMAN: Updated bundle based on EN rev109039
		109206: FRENCH: Updated bundle based on EN rev109039
		109223: GERMAN: Updated bundle based on EN rev109039 - fixed single quotes
		109226: FRENCH: Updated bundle based on EN rev109039 - fixed single quotes
		109228: ITALIAN: Updated bundle based on EN rev109039 - fixed single quotes
		109230: FRENCH: Updated bundle based on EN rev109039 - fixed single quotes again
		109235: JAPANESE: Updated bundle based on EN rev109039
		109293: SPANISH: Updated bundle based on EN rev109039
		109300: DUTCH: Updated bundle based on EN rev109039
		109412:	- Refactored the CMM JMX support to return CompositeData for performance reasons.
			- Reorganised a few of CMM classes/interfaces to make it easier for merging to alfresco core.
			- A minor fixes as a result of Find Bugs analysis.
			- Added the minimum and maximum repo versions for CMM module.
		109421: NORWEGIAN: Updated bundle based on EN rev109039
		109424: BRAZILIAN PORTUGUESE: Updated bundle based on EN rev109039
		109426: RUSSIAN: Updated bundle based on EN rev109039
		109427: CHINESE: Updated bundle based on EN rev10903
   109475: Added CMM Model into the core services (missed from previous commit).
   109480: SHA-723: Added custom models analytics in HeartBeat data.
   109481: SHA-528: Added GROUP_ALFRESCO_MODEL_ADMINISTRATORS_AUTHORITY patch.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@109490 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jamal Kaabi-Mofrad
2015-08-04 01:56:12 +00:00
parent 64452b59c0
commit 7ec60dc9c2
48 changed files with 8962 additions and 2 deletions

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=Model name can't be null.
cmm.rest_api.model_invalid=Invalid custom model.
cmm.rest_api.model_status_null=Model status can't be null.
cmm.rest_api.model_name_cannot_update=You can't update the model name.
cmm.rest_api.model_update_failure=We couldn't update the model.
cmm.rest_api.model_download_failure=We couldn't create a download node.
cmm.rest_api.model_namespace_uri_null=The model namespace URI can't be null.
cmm.rest_api.model_namespace_uri_invalid=The namespace URI is invalid. Use letters, numbers and URI characters only.
cmm.rest_api.model_namespace_prefix_null=Model namespace prefix can't be null.
# Type
cmm.rest_api.type_name_null=Type name can't be null.
cmm.rest_api.type_create_failure=We couldn't create the type.
cmm.rest_api.type_update_failure=We couldn't update the type.
cmm.rest_api.type_parent_cannot_update=You can't update the type's parent in an active custom model.
cmm.rest_api.type_parent_not_exist=You can''t set the type''s parent to ''{0}'', because the type ''{0}'' doesn''t exist.
cmm.rest_api.type_cannot_delete=You can't delete a type in an active model.
cmm.rest_api.type_delete_failure=We couldn't delete the type.
# Aspect
cmm.rest_api.aspect_name_null=Aspect name can't be null.
cmm.rest_api.aspect_create_failure=We couldn't create the aspect.
cmm.rest_api.aspect_update_failure=We couldn't update the aspect.
cmm.rest_api.aspect_parent_cannot_update=You can't update the aspect's parent in an active custom model.
cmm.rest_api.aspect_parent_not_exist=You can''t set the aspect''s parent to ''{0}'', because the aspect ''{0}'' doesn''t exist.
cmm.rest_api.aspect_cannot_delete=You can't delete an aspect in an active model.
cmm.rest_api.aspect_delete_failure=We couldn't delete the aspect.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=You can''t delete ''{0}'' as ''{1}'' depends on it.
# Constraint
cmm.rest_api.constraint_name_null=Constraint name can't be null.
cmm.rest_api.constraint_create_failure=We couldn't create constraint.
cmm.rest_api.constraint_parameter_name_null=Constraint parameter name can't be null.
cmm.rest_api.constraint_type_null=Custom constraint must have a 'type' attribute.
cmm.rest_api.constraint_ref_not_defined=Constraint reference ''{0}'' isn'' t defined by this model.
cmm.rest_api.regex_constraint_invalid_expression=REGEX expression ''{0}'' isn''t valid.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' isn''t a valid ''double'' value for MINMAX parameter ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=Maximum value of the MINMAX constraint must be greater than zero.
cmm.rest_api.minmax_constraint_invalid_use=MINMAX constraint can only be used with numeric data type.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' isn''t a valid ''int'' value for LENGTH parameter ''{1}''.
cmm.rest_api.length_constraint_invalid_use=You can only use the LENGTH constraint with TEXT, CONTENT and MLTEXT data types.
# Property
cmm.rest_api.property_name_null=Property name can't be null.
cmm.rest_api.property_create_update_failure=We couldn't create/update property.
cmm.rest_api.property_delete_failure=We couldn't delete the property.
cmm.rest_api.property_datatype_invalid=''{0}'' isn''t a valid data type format. A valid format should consist of a namespace prefix, a colon, and a name, for example: d:text.
cmm.rest_api.properties_empty_null=Properties can't be empty or null.
cmm.rest_api.property_create_name_already_in_use=We couldn''t create the property as the property name ''{0}'' is already in use.
cmm.rest_api.property_update_prop_not_found=We couldn''t find a property that matches ''{0}''.
cmm.rest_api.property_change_datatype_err=You can't change the data type of a property in an active model.
cmm.rest_api.property_change_mandatory_opt_err=You can't change the mandatory option of a property in an active model.
cmm.rest_api.property_change_mandatory_enforced_opt_err=You can't change the mandatory-enforced option of a property in an active model.
cmm.rest_api.property_change_multi_valued_opt_err=You can't change the multi-valued option of a property in an active model.
# validation
cmm.rest_api.input_validation_err=''{0}'' isn''t a valid value. Use numbers, letters, hyphens (-) and underscores (_) only.
cmm.rest_api.prefix_not_registered=There isn''t a namespace prefix registered for the URI ''{0}''. Make sure the model is active.
cmm.rest_api.prefixed_qname_invalid=''{0}'' isn''t a valid prefixed QName value. {1}
cmm.rest_api.circular_dependency_err=A circular dependency was detected. You can''t set parent ''{0}'', as it''s model already depends on ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' isn''t a valid prefixed QName format. A valid format should consist of a namespace prefix, a colon, and a name, for example: cm:content.
# model import
cmm.rest_api.model.import_namespace_multiple_found=The custom model can only have one namespace. We found ''{0}''.
cmm.rest_api.model.import_namespace_undefined=The custom model must define a namespace.
cmm.rest_api.model.import_associations_unsupported=The custom model doesn't support the 'associations' element.
cmm.rest_api.model.import_overrides_unsupported=The custom model doesn't support the 'overrides' element.
cmm.rest_api.model.import_mandatory_aspects_unsupported=The custom model doesn't support the 'mandatory-aspects' element.
cmm.rest_api.model.import_archive_unsupported=The custom model doesn't support the 'archive' element.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=The custom model doesn't support the 'includedInSuperTypeQuery' element.
cmm.rest_api.model.import_not_multi_part_req=Request isn't a multi-part form data.
cmm.rest_api.model.import_not_zip_format=''{0}'' isn''t a valid zip file.
cmm.rest_api.model.import_process_zip_file_failure=We couldn't process the zip file.
cmm.rest_api.model.import_no_zip_file_uploaded=We couldn't upload the zip file.
cmm.rest_api.model.import_invalid_zip_package=The zip file can't have more than two files. There should be one Model file and one Extension module file.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' isn''t a model or a Share extension module file.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' isn''t a valid model file.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' isn''t a valid Share extension module file.
cmm.rest_api.model.import_failure=We couldn't import the model.
cmm.rest_api.model.import_process_ext_module_file_failure=We couldn't process the Share extension module file.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=Modellname darf nicht Null sein.
cmm.rest_api.model_invalid=Ung\u00fcltiges parametriertes Modell.
cmm.rest_api.model_status_null=Modellstatus darf nicht Null sein.
cmm.rest_api.model_name_cannot_update=Sie k\u00f6nnen den Modellnamen nicht aktualisieren.
cmm.rest_api.model_update_failure=Wir konnten das Modell nicht aktualisieren.
cmm.rest_api.model_download_failure=Wir konnten keinen Download-Knoten erstellen.
cmm.rest_api.model_namespace_uri_null=Das Modell-Namespace-URI darf nicht Null sein.
cmm.rest_api.model_namespace_uri_invalid=Das Namespace-URI ist ung\u00fcltig. Verwenden Sie nur Buchstaben, Zahlen und URI-Zeichen.
cmm.rest_api.model_namespace_prefix_null=Modell-Namespace-Pr\u00e4fix darf nicht Null sein.
# Type
cmm.rest_api.type_name_null=Typenname darf nicht Null sein.
cmm.rest_api.type_create_failure=Wir konnten den Typ nicht erstellen.
cmm.rest_api.type_update_failure=Wir konnten den Typ nicht aktualisieren.
cmm.rest_api.type_parent_cannot_update=Sie k\u00f6nnen den Elterntyp in einem aktiven parametrierten Modell nicht aktualisieren.
cmm.rest_api.type_parent_not_exist=Sie k\u00f6nnen den Elterntyp nicht auf ''{0}'' setzen, weil es den Typ ''{0}'' nicht gibt.
cmm.rest_api.type_cannot_delete=Sie k\u00f6nnen einen Typ in einem aktiven Modell nicht l\u00f6schen.
cmm.rest_api.type_delete_failure=Wir konnten den Typ nicht l\u00f6schen.
# Aspect
cmm.rest_api.aspect_name_null=Aspektname darf nicht Null sein.
cmm.rest_api.aspect_create_failure=Wir konnten den Aspekt nicht erstellen.
cmm.rest_api.aspect_update_failure=Wir konnten den Aspekt nicht aktualisieren.
cmm.rest_api.aspect_parent_cannot_update=Sie k\u00f6nnen den Elternaspekt in einem aktiven parametrierten Modell nicht aktualisieren.
cmm.rest_api.aspect_parent_not_exist=Sie k\u00f6nnen den Elternaspekt nicht auf ''{0}'' setzen, weil es den Aspekt ''{0}'' nicht gibt.
cmm.rest_api.aspect_cannot_delete=Sie k\u00f6nnen einen Aspekt in einem aktiven Modell nicht l\u00f6schen.
cmm.rest_api.aspect_delete_failure=Wir konnten den Aspekt nicht l\u00f6schen.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=Sie k\u00f6nnen ''{0}'' nicht l\u00f6schen, weil ''{1}'' davon abh\u00e4ngt.
# Constraint
cmm.rest_api.constraint_name_null=Constraint-Name darf nicht Null sein.
cmm.rest_api.constraint_create_failure=Wir konnten den Constraint nicht erstellen.
cmm.rest_api.constraint_parameter_name_null=Constraint-Parametername darf nicht Null sein.
cmm.rest_api.constraint_type_null=Parametrierter Constraint muss ein Typenattribut haben.
cmm.rest_api.constraint_ref_not_defined=Constraint-Verweis ''{0}'' ist von diesem Modell nicht definiert.
cmm.rest_api.regex_constraint_invalid_expression=REGEX-Ausdruck ''{0}'' ist nicht zul\u00e4ssig.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' ist kein zul\u00e4ssiger Doppelparameter f\u00fcr MINMAX-Parameter ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=H\u00f6chstwert des MINMAX-Constraints muss gr\u00f6\u00dfer als Null sein.
cmm.rest_api.minmax_constraint_invalid_use=MINMAX-Constraint kann nur mit numerischem Datentyp verwendet werden.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' ist kein zul\u00e4ssiger Integer-Wert f\u00fcr LENGTH-Parameter ''{1}''.
cmm.rest_api.length_constraint_invalid_use=Sie k\u00f6nnen den LENGTH-Constraint nur mit den Datentypen TEXT, CONTENT und MLTEXT verwenden.
# Property
cmm.rest_api.property_name_null=Eigenschaftenname darf nicht Null sein.
cmm.rest_api.property_create_update_failure=Wir konnten die Eigenschaft nicht erstellen/aktualisieren.
cmm.rest_api.property_delete_failure=Wir konnten die Eigenschaft nicht l\u00f6schen.
cmm.rest_api.property_datatype_invalid=''{0}'' ist kein zul\u00e4ssiges Datentyp-Format. Ein zul\u00e4ssiges Format besteht aus einem Namespace-Pr\u00e4fix, einem Doppelpunkt und einem Namen (zum Beispiel d:text).
cmm.rest_api.properties_empty_null=Eigenschaften d\u00fcrfen nicht leer oder Null sein.
cmm.rest_api.property_create_name_already_in_use=Wir konnten die Eigenschaft nicht erstellen, weil der Eigenschaftenname ''{0}'' bereits verwendet wird.
cmm.rest_api.property_update_prop_not_found=Wir konnten keine Eigenschaft finden, die mit ''{0}'' \u00fcbereinstimmt.
cmm.rest_api.property_change_datatype_err=Der Datentyp einer Eigenschaft in einem aktiven Modell kann nicht ge\u00e4ndert werden.
cmm.rest_api.property_change_mandatory_opt_err=Die Option ''Obligatorisch'' einer Eigenschaft in einem aktiven Modell kann nicht ge\u00e4ndert werden.
cmm.rest_api.property_change_mandatory_enforced_opt_err=Die Option ''Obligatorisch (erzwungen)'' einer Eigenschaft in einem aktiven Modell kann nicht ge\u00e4ndert werden.
cmm.rest_api.property_change_multi_valued_opt_err=Die Option f\u00fcr mehrere Werte einer Eigenschaft in einem aktiven Modell kann nicht ge\u00e4ndert werden.
# validation
cmm.rest_api.input_validation_err=''{0}'' ist kein zul\u00e4ssiger Wert. Verwenden Sie nur Zahlen, Buchstaben, Bindestriche (-) und Unterstriche (_).
cmm.rest_api.prefix_not_registered=F\u00fcr das URI ''{0}'' ist kein Namespace-Pr\u00e4fix registriert. Stellen Sie sicher, dass das Modell aktiv ist.
cmm.rest_api.prefixed_qname_invalid=''{0}'' ist kein zul\u00e4ssiger QName-Wert mit Pr\u00e4fix. {1}
cmm.rest_api.circular_dependency_err=Es wurde eine Ringabh\u00e4ngigkeit entdeckt. Eltern-''{0}'' kann nicht eingerichtet werden, weil sein Modell bereits von ''{1}'' abh\u00e4ngt.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' ist kein zul\u00e4ssiges QName-Format mit Pr\u00e4fix. Ein zul\u00e4ssiges Format besteht aus einem Namespace-Pr\u00e4fix, einem Doppelpunkt und einem Namen (zum Beispiel cm:content).
# model import
cmm.rest_api.model.import_namespace_multiple_found=Das parametrierte Modell darf nur \u00fcber einen Namespace verf\u00fcgen. Wir haben ''{0}'' gefunden.
cmm.rest_api.model.import_namespace_undefined=Das parametrierte Modell muss einen Namespace definieren.
cmm.rest_api.model.import_associations_unsupported=Das parametrierte Modell unterst\u00fctzt das Element 'associations' nicht.
cmm.rest_api.model.import_overrides_unsupported=Das parametrierte Modell unterst\u00fctzt das Element 'overrides' nicht.
cmm.rest_api.model.import_mandatory_aspects_unsupported=Das parametrierte Modell unterst\u00fctzt das Element 'mandatory-aspects' nicht.
cmm.rest_api.model.import_archive_unsupported=Das parametrierte Modell unterst\u00fctzt das Element 'archive' nicht.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=Das parametrierte Modell unterst\u00fctzt das Element 'includedInSuperTypeQuery' nicht.
cmm.rest_api.model.import_not_multi_part_req=Bei der Anfrage handelt es sich nicht um mehrteilige Formulardaten.
cmm.rest_api.model.import_not_zip_format=''{0}'' ist keine zul\u00e4ssige ZIP-Datei.
cmm.rest_api.model.import_process_zip_file_failure=Wir konnten die ZIP-Datei nicht verarbeiten.
cmm.rest_api.model.import_no_zip_file_uploaded=Wir konnten die ZIP-Datei nicht hochladen.
cmm.rest_api.model.import_invalid_zip_package=Die ZIP-Datei darf nicht mehr als zwei Dateien beinhalten. Es sollte eine Modelldatei und eine Erweiterungsmodul-Datei geben.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' ist keine Modell- oder Share-Erweiterungs-Modul-Datei.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' ist keine zul\u00e4ssige Modelldatei.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' ist keine zul\u00e4ssige Share-Erweiterungs-Modul-Datei.
cmm.rest_api.model.import_failure=Wir konnten das Modell nicht importieren.
cmm.rest_api.model.import_process_ext_module_file_failure=Wir konnten die Share-Erweiterungs-Modul-Datei nicht verarbeiten.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=El nombre del modelo no puede ser nulo.
cmm.rest_api.model_invalid=Modelo personalizado no v\u00e1lido.
cmm.rest_api.model_status_null=El estado del modelo no puede ser nulo.
cmm.rest_api.model_name_cannot_update=No puede actualizar el nombre del modelo.
cmm.rest_api.model_update_failure=No se ha podido actualizar el modelo.
cmm.rest_api.model_download_failure=No se ha podido crear un nodo de descarga.
cmm.rest_api.model_namespace_uri_null=La URI de espacio de nombres del modelo no puede ser nula.
cmm.rest_api.model_namespace_uri_invalid=La URI de espacio de nombres no es v\u00e1lida. Utilice n\u00fameros, letras y caracteres URI solamente.
cmm.rest_api.model_namespace_prefix_null=El prefijo de espacio de nombres no puede ser nulo.
# Type
cmm.rest_api.type_name_null=El nombre del tipo no puede ser nulo.
cmm.rest_api.type_create_failure=No se ha podido crear el tipo.
cmm.rest_api.type_update_failure=No se ha podido actualizar el tipo.
cmm.rest_api.type_parent_cannot_update=No puede actualizar el padre del tipo en un modelo personalizado activo.
cmm.rest_api.type_parent_not_exist=No puede establecer el padre del tipo en ''{0}'', porque el tipo ''{0}'' no existe.
cmm.rest_api.type_cannot_delete=No puede eliminar un tipo en un modelo activo.
cmm.rest_api.type_delete_failure=No se ha podido eliminar el tipo.
# Aspect
cmm.rest_api.aspect_name_null=El nombre del aspecto no puede ser nulo.
cmm.rest_api.aspect_create_failure=No se ha podido crear el aspecto.
cmm.rest_api.aspect_update_failure=No se ha podido actualizar el aspecto.
cmm.rest_api.aspect_parent_cannot_update=No puede actualizar el padre del aspecto en un modelo personalizado activo.
cmm.rest_api.aspect_parent_not_exist=No puede establecer el padre del aspecto en ''{0}'', porque el aspecto ''{0}'' no existe.
cmm.rest_api.aspect_cannot_delete=No puede eliminar un aspecto en un modelo activo.
cmm.rest_api.aspect_delete_failure=No se ha podido eliminar el aspecto.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=No puede eliminar ''{0}'' ya que ''{1}'' depende de \u00e9l.
# Constraint
cmm.rest_api.constraint_name_null=El nombre de la restricci\u00f3n no puede ser nulo.
cmm.rest_api.constraint_create_failure=No se ha podido crear la restricci\u00f3n.
cmm.rest_api.constraint_parameter_name_null=El nombre del par\u00e1metro de la restricci\u00f3n no puede ser nulo.
cmm.rest_api.constraint_type_null=La restricci\u00f3n personalizada debe tener un atributo 'tipo'.
cmm.rest_api.constraint_ref_not_defined=La referencia de la restricci\u00f3n ''{0}'' no la ha definido este modelo.
cmm.rest_api.regex_constraint_invalid_expression=La expresi\u00f3n REGEX ''{0}'' no es v\u00e1lida.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' no es un valor doble v\u00e1lido para el par\u00e1metro MINMAX ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=El valor m\u00e1ximo de la restricci\u00f3n MINMAX debe ser superior a cero.
cmm.rest_api.minmax_constraint_invalid_use=La restricci\u00f3n MINMAX solo puede usarse con un tipo de datos num\u00e9ricos.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' no es un valor ''entero'' v\u00e1lido para el par\u00e1metro LENGTH ''{1}''.
cmm.rest_api.length_constraint_invalid_use=Solo puede usar la restricci\u00f3n LENGTH con los tipos de datos TEXT, CONTENT y MLTEXT.
# Property
cmm.rest_api.property_name_null=El nombre de la propiedad no puede ser nulo.
cmm.rest_api.property_create_update_failure=No se ha podido crear/actualizar la propiedad.
cmm.rest_api.property_delete_failure=No se ha podido eliminar la propiedad.
cmm.rest_api.property_datatype_invalid=''{0}'' no es un formato de tipo de datos v\u00e1lido. Un formato v\u00e1lido debe incluir un prefijo de espacio de nombres, dos puntos y un nombre, por ejemplo, d:text.
cmm.rest_api.properties_empty_null=Las propiedades no pueden estar vac\u00edas o ser nulas.
cmm.rest_api.property_create_name_already_in_use=No se ha podido crear la propiedad porque el nombre de propiedad ''{0}'' ya se est\u00e1 usando.
cmm.rest_api.property_update_prop_not_found=No se ha podido encontrar una propiedad que coincida con ''{0}''.
cmm.rest_api.property_change_datatype_err=No puede cambiar el tipo de datos de una propiedad en un modelo activo.
cmm.rest_api.property_change_mandatory_opt_err=No puede cambiar la opci\u00f3n obligatoria de una propiedad en un modelo activo.
cmm.rest_api.property_change_mandatory_enforced_opt_err=No puede cambiar la opci\u00f3n obligatoria (exigida) de una propiedad en un modelo activo.
cmm.rest_api.property_change_multi_valued_opt_err=No puede cambiar la opci\u00f3n de m\u00faltiples valores de una propiedad en un modelo activo.
# validation
cmm.rest_api.input_validation_err=''{0}'' no es un valor v\u00e1lido. Utilice n\u00fameros, letras, guiones (-) y guiones bajos (_) solamente.
cmm.rest_api.prefix_not_registered=No existe un prefijo de espacio de nombres registrado para la URI ''{0}''. Aseg\u00farese de que el modelo est\u00e1 activo.
cmm.rest_api.prefixed_qname_invalid=''{0}'' no es un valor QName con prefijo v\u00e1lido. {1}
cmm.rest_api.circular_dependency_err=Se ha detectado una dependencia circular. No puede establecer el padre ''{0}'', ya que su modelo ya depende de ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' no es un formato QName con prefijo v\u00e1lido. Un formato v\u00e1lido debe incluir un prefijo de espacio de nombres, dos puntos y un nombre, por ejemplo, cm:content.
# model import
cmm.rest_api.model.import_namespace_multiple_found=El modelo personalizado solo puede tener un espacio de nombres. Se encontr\u00f3 ''{0}''.
cmm.rest_api.model.import_namespace_undefined=El modelo personalizado debe definir un espacio de nombres.
cmm.rest_api.model.import_associations_unsupported=El modelo personalizado no es compatible con el elemento 'associations'.
cmm.rest_api.model.import_overrides_unsupported=El modelo personalizado no es compatible con el elemento 'overrides'.
cmm.rest_api.model.import_mandatory_aspects_unsupported=El modelo personalizado no es compatible con el elemento 'mandatory-aspects'.
cmm.rest_api.model.import_archive_unsupported=El modelo personalizado no es compatible con el elemento 'archive'.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=El modelo personalizado no es compatible con el elemento 'includedInSuperTypeQuery'.
cmm.rest_api.model.import_not_multi_part_req=La solicitud no equivale a datos de formulario de varias partes.
cmm.rest_api.model.import_not_zip_format=''{0}'' no es un fichero zip v\u00e1lido.
cmm.rest_api.model.import_process_zip_file_failure=No se ha podido procesar el fichero zip.
cmm.rest_api.model.import_no_zip_file_uploaded=No se ha podido subir el fichero zip.
cmm.rest_api.model.import_invalid_zip_package=El fichero zip no puede tener m\u00e1s de dos ficheros. Debe hacer un fichero de modelo y un fichero de m\u00f3dulo de extensi\u00f3n.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' no es un modelo ni un fichero de m\u00f3dulo de extensi\u00f3n de Share.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' no es un fichero de modelo v\u00e1lido.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' no es un fichero de m\u00f3dulo de extensi\u00f3n de Share v\u00e1lido.
cmm.rest_api.model.import_failure=No se ha podido importar el modelo.
cmm.rest_api.model.import_process_ext_module_file_failure=No se ha podido procesar el fichero de m\u00f3dulo de extensi\u00f3n de Share.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=Le nom du mod\u00e8le ne peut pas \u00eatre null.
cmm.rest_api.model_invalid=Mod\u00e8le personnalis\u00e9 non valide.
cmm.rest_api.model_status_null=Le statut du mod\u00e8le ne peut pas \u00eatre null.
cmm.rest_api.model_name_cannot_update=Impossible de mettre \u00e0 jour le nom du mod\u00e8le.
cmm.rest_api.model_update_failure=Impossible de mettre \u00e0 jour le mod\u00e8le.
cmm.rest_api.model_download_failure=Impossible de cr\u00e9er un n\u0153ud de t\u00e9l\u00e9chargement.
cmm.rest_api.model_namespace_uri_null=L'URI d'espace de nom du mod\u00e8le ne peut pas \u00eatre null.
cmm.rest_api.model_namespace_uri_invalid=L'URI d'espace de nom n'est pas valide. Utilisez uniquement des lettres, des chiffres et des caract\u00e8res URI.
cmm.rest_api.model_namespace_prefix_null=Le pr\u00e9fixe d'espace de nom du mod\u00e8le ne peut pas \u00eatre null.
# Type
cmm.rest_api.type_name_null=Le nom du type ne peut pas \u00eatre null.
cmm.rest_api.type_create_failure=Impossible de cr\u00e9er le type.
cmm.rest_api.type_update_failure=Impossible de mettre \u00e0 jour le type.
cmm.rest_api.type_parent_cannot_update=Impossible de mettre \u00e0 jour le parent du type dans un mod\u00e8le personnalis\u00e9 actif.
cmm.rest_api.type_parent_not_exist=Impossible de d\u00e9finir le parent du type sur ''{0}'', car le type ''{0}'' n''existe pas.
cmm.rest_api.type_cannot_delete=Impossible de supprimer un type dans un mod\u00e8le actif.
cmm.rest_api.type_delete_failure=Impossible de supprimer le type.
# Aspect
cmm.rest_api.aspect_name_null=Le nom de l'aspect ne peut pas \u00eatre null.
cmm.rest_api.aspect_create_failure=Impossible de cr\u00e9er l'aspect.
cmm.rest_api.aspect_update_failure=Impossible de mettre \u00e0 jour l'aspect.
cmm.rest_api.aspect_parent_cannot_update=Impossible de mettre \u00e0 jour le parent de l'aspect dans un mod\u00e8le personnalis\u00e9 actif.
cmm.rest_api.aspect_parent_not_exist=Impossible de d\u00e9finir le parent de l''aspect sur ''{0}'', car l''aspect ''{0}'' n''existe pas.
cmm.rest_api.aspect_cannot_delete=Impossible de supprimer un aspect dans un mod\u00e8le actif.
cmm.rest_api.aspect_delete_failure=Impossible de supprimer l'aspect.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=Impossible de supprimer ''{0}'' car ''{1}'' en d\u00e9pend.
# Constraint
cmm.rest_api.constraint_name_null=Le nom de la contrainte ne peut pas \u00eatre null.
cmm.rest_api.constraint_create_failure=Impossible de cr\u00e9er la contrainte.
cmm.rest_api.constraint_parameter_name_null=Le nom du param\u00e8tre de la contrainte ne peut pas \u00eatre null.
cmm.rest_api.constraint_type_null=La contrainte personnalis\u00e9e doit avoir un attribut 'type'.
cmm.rest_api.constraint_ref_not_defined=La r\u00e9f\u00e9rence de la contrainte ''{0}'' n''est pas d\u00e9finie par ce mod\u00e8le.
cmm.rest_api.regex_constraint_invalid_expression=L''expression REGEX ''{0}'' n''est pas valide.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' n''est pas une valeur ''double'' valide pour le param\u00e8tre MINMAX ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=La valeur maximum de la contrainte MINMAX doit \u00eatre sup\u00e9rieure \u00e0 z\u00e9ro.
cmm.rest_api.minmax_constraint_invalid_use=La contrainte MINMAX peut \u00eatre utilis\u00e9e uniquement avec un type de donn\u00e9es num\u00e9rique.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' n''est pas une valeur ''entier'' valide pour le param\u00e8tre LENGTH ''{1}''.
cmm.rest_api.length_constraint_invalid_use=La contrainte LENGTH peut \u00eatre utilis\u00e9e uniquement avec les types de donn\u00e9es TEXT, CONTENT et MLTEXT.
# Property
cmm.rest_api.property_name_null=Le nom de la propri\u00e9t\u00e9 ne peut pas \u00eatre null.
cmm.rest_api.property_create_update_failure=Impossible de cr\u00e9er/mettre \u00e0 jour la propri\u00e9t\u00e9.
cmm.rest_api.property_delete_failure=Impossible de supprimer la propri\u00e9t\u00e9.
cmm.rest_api.property_datatype_invalid=''{0}'' n''est pas un format de type de donn\u00e9es valide. Un format valide se compose d''un pr\u00e9fixe d''espace de nom, suivi de deux-points et d''un nom, par exemple\u00a0: d:text.
cmm.rest_api.properties_empty_null=Les propri\u00e9t\u00e9s ne peuvent pas \u00eatre vides ou null.
cmm.rest_api.property_create_name_already_in_use=Impossible de cr\u00e9er la propri\u00e9t\u00e9 car le nom de propri\u00e9t\u00e9 ''{0}'' est d\u00e9j\u00e0 utilis\u00e9.
cmm.rest_api.property_update_prop_not_found=Impossible de trouver une propri\u00e9t\u00e9 qui correspond \u00e0 ''{0}''.
cmm.rest_api.property_change_datatype_err=Vous ne pouvez pas modifier le type de donn\u00e9es d'une propri\u00e9t\u00e9 dans un mod\u00e8le actif.
cmm.rest_api.property_change_mandatory_opt_err=Vous ne pouvez pas modifier l'option obligatoire d'une propri\u00e9t\u00e9 dans un mod\u00e8le actif.
cmm.rest_api.property_change_mandatory_enforced_opt_err=Vous ne pouvez pas modifier l'option obligatoire impos\u00e9e d'une propri\u00e9t\u00e9 dans un mod\u00e8le actif.
cmm.rest_api.property_change_multi_valued_opt_err=Vous ne pouvez pas modifier l'option \u00e0 valeurs multiples d'une propri\u00e9t\u00e9 dans un mod\u00e8le actif.
# validation
cmm.rest_api.input_validation_err=''{0}'' n''est pas une valeur valide. Utilisez des chiffres, des lettres, des tirets (-) et des traits de soulignement (_) uniquement.
cmm.rest_api.prefix_not_registered=Aucun pr\u00e9fixe d''espace de nom enregistr\u00e9 pour l''URI ''{0}''. Assurez-vous que le mod\u00e8le est actif.
cmm.rest_api.prefixed_qname_invalid=''{0}'' n''est pas une valeur QName pr\u00e9fix\u00e9e valide. {1}
cmm.rest_api.circular_dependency_err=Une d\u00e9pendance circulaire a \u00e9t\u00e9 d\u00e9tect\u00e9e. Impossible de d\u00e9finir le parent ''{0}'' car son mod\u00e8le d\u00e9pend d\u00e9j\u00e0 de ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' n''est pas un format QName pr\u00e9fix\u00e9 valide. Un format valide se compose d''un pr\u00e9fixe d''espace de nom, suivi de deux-points et d''un nom, par exemple\u00a0: cm:content.
# model import
cmm.rest_api.model.import_namespace_multiple_found=Le mod\u00e8le personnalis\u00e9 ne peut avoir qu''un seul espace de nom. ''{0}'' a \u00e9t\u00e9 trouv\u00e9.
cmm.rest_api.model.import_namespace_undefined=Le mod\u00e8le personnalis\u00e9 doit d\u00e9finir un espace de nom.
cmm.rest_api.model.import_associations_unsupported=Le mod\u00e8le personnalis\u00e9 ne prend pas en charge l'\u00e9l\u00e9ment 'associations'.
cmm.rest_api.model.import_overrides_unsupported=Le mod\u00e8le personnalis\u00e9 ne prend pas en charge l'\u00e9l\u00e9ment 'overrides'.
cmm.rest_api.model.import_mandatory_aspects_unsupported=Le mod\u00e8le personnalis\u00e9 ne prend pas en charge l'\u00e9l\u00e9ment 'mandatory-aspects'.
cmm.rest_api.model.import_archive_unsupported=Le mod\u00e8le personnalis\u00e9 ne prend pas en charge l'\u00e9l\u00e9ment 'archive'.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=Le mod\u00e8le personnalis\u00e9 ne prend pas en charge l'\u00e9l\u00e9ment 'includedInSuperTypeQuery'.
cmm.rest_api.model.import_not_multi_part_req=La requ\u00eate n'est pas une donn\u00e9e de formulaire \u00e0 parties multiples.
cmm.rest_api.model.import_not_zip_format=''{0}'' n''est pas un fichier zip valide.
cmm.rest_api.model.import_process_zip_file_failure=Impossible de traiter le fichier zip.
cmm.rest_api.model.import_no_zip_file_uploaded=Impossible d'importer le fichier zip.
cmm.rest_api.model.import_invalid_zip_package=Le fichier zip ne peut pas comporter plus de deux fichiers. Il doit comporter un fichier de mod\u00e8le et un fichier de module d'extension.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' n''est pas un fichier de mod\u00e8le ou de module d''extension Share.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' n''est pas un fichier de mod\u00e8le valide.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' n''est pas un fichier de module d''extension Share valide.
cmm.rest_api.model.import_failure=Impossible d'importer le mod\u00e8le.
cmm.rest_api.model.import_process_ext_module_file_failure=Impossible de traiter le fichier de module d'extension Share.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=Il nome modello non pu\u00f2 essere nullo.
cmm.rest_api.model_invalid=Modello personalizzato non valido.
cmm.rest_api.model_status_null=Lo stato del modello non pu\u00f2 essere nullo.
cmm.rest_api.model_name_cannot_update=Impossibile aggiornare il nome modello.
cmm.rest_api.model_update_failure=Impossibile aggiornare il modello.
cmm.rest_api.model_download_failure=Impossibile creare un nodo di download.
cmm.rest_api.model_namespace_uri_null=L'URI dello spazio dei nomi del modello non pu\u00f2 essere nullo.
cmm.rest_api.model_namespace_uri_invalid=L'URI dello spazio dei nomi non \u00e8 valido. Utilizzare solo lettere, numeri e caratteri URI.
cmm.rest_api.model_namespace_prefix_null=Il prefisso dello spazio dei nomi del modello non pu\u00f2 essere nullo.
# Type
cmm.rest_api.type_name_null=Il nome tipo non pu\u00f2 essere nullo.
cmm.rest_api.type_create_failure=Impossibile creare il tipo.
cmm.rest_api.type_update_failure=Impossibile aggiornare il tipo.
cmm.rest_api.type_parent_cannot_update=Impossibile aggiornare il genitore del tipo in un modello personalizzato attivo.
cmm.rest_api.type_parent_not_exist=Impossibile impostare il genitore del tipo su ''{0}'' perch\u00e9 il tipo ''{0}'' non esiste.
cmm.rest_api.type_cannot_delete=Impossibile eliminare un tipo in un modello attivo.
cmm.rest_api.type_delete_failure=Impossibile eliminare il tipo.
# Aspect
cmm.rest_api.aspect_name_null=Il nome aspetto non pu\u00f2 essere nullo.
cmm.rest_api.aspect_create_failure=Impossibile creare l'aspetto.
cmm.rest_api.aspect_update_failure=Impossibile aggiornare l'aspetto.
cmm.rest_api.aspect_parent_cannot_update=Impossibile aggiornare il genitore dell'aspetto in un modello personalizzato attivo.
cmm.rest_api.aspect_parent_not_exist=Impossibile impostare il genitore dell''aspetto su ''{0}'' perch\u00e9 l''aspetto ''{0}'' non esiste.
cmm.rest_api.aspect_cannot_delete=Impossibile eliminare un aspetto in un modello attivo.
cmm.rest_api.aspect_delete_failure=Impossibile eliminare l'aspetto.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=Impossibile eliminare ''{0}'' perch\u00e9 ''{1}'' dipende da questo.
# Constraint
cmm.rest_api.constraint_name_null=Il nome vincolo non pu\u00f2 essere nullo.
cmm.rest_api.constraint_create_failure=Impossibile creare il vincolo.
cmm.rest_api.constraint_parameter_name_null=Il parametro del vincolo non pu\u00f2 essere nullo.
cmm.rest_api.constraint_type_null=Il vincolo personalizzato deve avere un attributo ''tipo''.
cmm.rest_api.constraint_ref_not_defined=Il riferimento vincolo ''{0}'' non \u00e8 definito da questo modello.
cmm.rest_api.regex_constraint_invalid_expression=L''espressione REGEX ''{0}'' non \u00e8 valida.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' non \u00e8 un valore ''doppio'' valido per il parametro MINMAX ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=Il valore massimo del vincolo MINMAX deve essere maggiore di zero.
cmm.rest_api.minmax_constraint_invalid_use=Il vincolo MINMAX pu\u00f2 essere utilizzato solo con il tipo di dati numerico.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' non \u00e8 un valore ''intero'' valido per il parametro LENGTH ''{1}''.
cmm.rest_api.length_constraint_invalid_use=\u00c8 possibile utilizzare solo il vincolo LENGTH con i tipi di dati TEXT, CONTENT e MLTEXT.
# Property
cmm.rest_api.property_name_null=Il nome propriet\u00e0 non pu\u00f2 essere nullo.
cmm.rest_api.property_create_update_failure=Impossibile creare/aggiornare la propriet\u00e0.
cmm.rest_api.property_delete_failure=Impossibile eliminare la propriet\u00e0.
cmm.rest_api.property_datatype_invalid=''{0}'' non \u00e8 un formato tipo di dati valido. Un formato valido deve essere costituito da un prefisso dello spazio dei nomi, due punti e un nome, ad esempio: d:testo.
cmm.rest_api.properties_empty_null=Le propriet\u00e0 non possono essere vuote o nulle.
cmm.rest_api.property_create_name_already_in_use=Impossibile creare la propriet\u00e0 perch\u00e9 il nome propriet\u00e0 ''{0}'' \u00e8 gi\u00e0 in uso.
cmm.rest_api.property_update_prop_not_found=Nessuna propriet\u00e0 trovata che corrisponda a ''{0}''.
cmm.rest_api.property_change_datatype_err=Non \u00e8 possibile modificare il tipo di dati di una propriet\u00e0 in un modello attivo.
cmm.rest_api.property_change_mandatory_opt_err=Non \u00e8 possibile modificare l'opzione obbligatoria di una propriet\u00e0 in un modello attivo.
cmm.rest_api.property_change_mandatory_enforced_opt_err=Non \u00e8 possibile modificare l'opzione obbligatoria (imposta) di una propriet\u00e0 in un modello attivo.
cmm.rest_api.property_change_multi_valued_opt_err=Non \u00e8 possibile modificare l'opzione multivalore di una propriet\u00e0 in un modello attivo.
# validation
cmm.rest_api.input_validation_err=''{0}'' non \u00e8 un valore valido. Utilizzare solo numeri, lettere, trattini (-) e caratteri di sottolineatura (_).
cmm.rest_api.prefix_not_registered=Non esiste un prefisso dello spazio dei nomi registrato per l''URI ''{0}''. Assicurarsi che il modello sia attivo.
cmm.rest_api.prefixed_qname_invalid=''{0}'' non \u00e8 un valore QName con prefisso valido. {1}
cmm.rest_api.circular_dependency_err=\u00c8 stata rilevata una dipendenza circolare. Non \u00e8 possibile impostare il genitore''{0}'' perch\u00e9 il modello associato dipende gi\u00e0 da ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' non \u00e8 un formato QName con prefisso valido. Un formato valido deve essere costituito da un prefisso dello spazio dei nomi, due punti e un nome, ad esempio: d:contenuto.
# model import
cmm.rest_api.model.import_namespace_multiple_found=Il modello personalizzato pu\u00f2 avere solo uno spazio dei nomi. \u00c8 stato trovato''{0}''.
cmm.rest_api.model.import_namespace_undefined=Il modello personalizzato deve definire uno spazio dei nomi.
cmm.rest_api.model.import_associations_unsupported=Il modello personalizzato non supporta l'elemento ''associations''.
cmm.rest_api.model.import_overrides_unsupported=Il modello personalizzato non supporta l'elemento ''overrides''.
cmm.rest_api.model.import_mandatory_aspects_unsupported=Il modello personalizzato non supporta l'elemento ''mandatory-aspects''.
cmm.rest_api.model.import_archive_unsupported=Il modello personalizzato non supporta l'elemento ''archive''.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=Il modello personalizzato non supporta l'elemento ''includedInSuperTypeQuery''.
cmm.rest_api.model.import_not_multi_part_req=La richiesta non rappresenta dati di un modulo a pi\u00f9 parti.
cmm.rest_api.model.import_not_zip_format=''{0}'' non \u00e8 un file zip valido.
cmm.rest_api.model.import_process_zip_file_failure=Impossibile elaborare il file zip.
cmm.rest_api.model.import_no_zip_file_uploaded=Impossibile caricare il file zip.
cmm.rest_api.model.import_invalid_zip_package=Il file zip non pu\u00f2 contenere pi\u00f9 di due file. Deve contenere un file Modello e un file Estensione.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' non \u00e8 un modello o un file modulo di estensione di Share.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' non \u00e8 un file modello valido.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}''non \u00e8 un file modulo di estensione di Share valido.
cmm.rest_api.model.import_failure=Impossibile importare il modello.
cmm.rest_api.model.import_process_ext_module_file_failure=Impossibile elaborare il file modulo di estensione di Share.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=\u30e2\u30c7\u30eb\u540d\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model_invalid=\u7121\u52b9\u306a\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u3067\u3059\u3002
cmm.rest_api.model_status_null=\u30e2\u30c7\u30eb\u306e\u30b9\u30c6\u30fc\u30bf\u30b9\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model_name_cannot_update=\u30e2\u30c7\u30eb\u540d\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model_update_failure=\u30e2\u30c7\u30eb\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.model_download_failure=\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30ce\u30fc\u30c9\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.model_namespace_uri_null=\u30e2\u30c7\u30eb\u306e\u540d\u524d\u7a7a\u9593 URI \u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model_namespace_uri_invalid=\u540d\u524d\u7a7a\u9593 URI \u304c\u7121\u52b9\u3067\u3059\u3002 \u82f1\u5b57\u3001\u6570\u5b57\u3001URI \u6587\u5b57\u3060\u3051\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002
cmm.rest_api.model_namespace_prefix_null=\u30e2\u30c7\u30eb\u306e\u540d\u524d\u7a7a\u9593\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
# Type
cmm.rest_api.type_name_null=\u30bf\u30a4\u30d7\u540d\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.type_create_failure=\u30bf\u30a4\u30d7\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.type_update_failure=\u30bf\u30a4\u30d7\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.type_parent_cannot_update=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u306e\u89aa\u30bf\u30a4\u30d7\u306f\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.type_parent_not_exist=\u30bf\u30a4\u30d7 ''{0}'' \u306f\u5b58\u5728\u3057\u306a\u3044\u305f\u3081\u3001''{0}'' \u306b\u89aa\u30bf\u30a4\u30d7\u306f\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.type_cannot_delete=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30e2\u30c7\u30eb\u306e\u30bf\u30a4\u30d7\u306f\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.type_delete_failure=\u30bf\u30a4\u30d7\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
# Aspect
cmm.rest_api.aspect_name_null=\u30a2\u30b9\u30da\u30af\u30c8\u540d\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.aspect_create_failure=\u30a2\u30b9\u30da\u30af\u30c8\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.aspect_update_failure=\u30a2\u30b9\u30da\u30af\u30c8\u3092\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.aspect_parent_cannot_update=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u306e\u89aa\u30a2\u30b9\u30da\u30af\u30c8\u306f\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.aspect_parent_not_exist=\u30a2\u30b9\u30da\u30af\u30c8 ''{0}'' \u306f\u5b58\u5728\u3057\u306a\u3044\u305f\u3081\u3001''{0}'' \u306b\u89aa\u30a2\u30b9\u30da\u30af\u30c8\u306f\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.aspect_cannot_delete=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30e2\u30c7\u30eb\u306e\u30a2\u30b9\u30da\u30af\u30c8\u306f\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.aspect_delete_failure=\u30a2\u30b9\u30da\u30af\u30c8\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=''{0}'' \u306f ''{1}'' \u306e\u4f9d\u5b58\u5148\u3067\u3042\u308b\u305f\u3081\u3001\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3002
# Constraint
cmm.rest_api.constraint_name_null=\u5236\u7d04\u540d\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.constraint_create_failure=\u5236\u7d04\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.constraint_parameter_name_null=\u5236\u7d04\u30d1\u30e9\u30e1\u30fc\u30bf\u540d\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.constraint_type_null=\u30ab\u30b9\u30bf\u30e0\u306e\u5236\u7d04\u306b\u306f 'type' \u5c5e\u6027\u304c\u5fc5\u8981\u3067\u3059\u3002
cmm.rest_api.constraint_ref_not_defined=\u5236\u7d04\u306e\u53c2\u7167 ''{0}'' \u306f\u3001\u3053\u306e\u30e2\u30c7\u30eb\u3067\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002
cmm.rest_api.regex_constraint_invalid_expression=REGEX \u8868\u73fe ''{0}'' \u304c\u7121\u52b9\u3067\u3059\u3002
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' \u306f MINMAX \u30d1\u30e9\u30e1\u30fc\u30bf ''{1}'' \u306e\u6709\u52b9\u306a\u500d\u7cbe\u5ea6\u5024\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.minmax_constraint_invalid_max_value=MINMAX \u5236\u7d04\u306e\u6700\u5927\u5024\u306f\u3001\u30bc\u30ed\u3088\u308a\u5927\u304d\u304f\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.minmax_constraint_invalid_use=MINMAX \u5236\u7d04\u306f\u3001\u6570\u5b57\u306e\u30c7\u30fc\u30bf\u578b\u3067\u3057\u304b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' \u306f\u3001LENGTH \u30d1\u30e9\u30e1\u30fc\u30bf ''{1}'' \u306e\u6709\u52b9\u306a\u6574\u6570\u5024\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.length_constraint_invalid_use=LENGTH \u5236\u7d04\u306f\u3001TEXT\u3001CONTENT\u3001MLTEXT \u306e\u30c7\u30fc\u30bf\u578b\u3067\u3057\u304b\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
# Property
cmm.rest_api.property_name_null=\u30d7\u30ed\u30d1\u30c6\u30a3\u540d\u306f\u30cc\u30eb\u306b\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.property_create_update_failure=\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u4f5c\u6210\u307e\u305f\u306f\u66f4\u65b0\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.property_delete_failure=\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u524a\u9664\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.property_datatype_invalid=''{0}'' \u306f\u6709\u52b9\u306a\u30c7\u30fc\u30bf\u578b\u5f62\u5f0f\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u6709\u52b9\u306a\u5f62\u5f0f\u306f\u3001\u540d\u524d\u7a7a\u9593\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u3001\u30b3\u30ed\u30f3 (:)\u3001\u540d\u524d\u306e\u7d44\u307f\u5408\u308f\u305b\u3067\u3059\u3002\u4f8b: d:text
cmm.rest_api.properties_empty_null=\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u7a7a\u307e\u305f\u306f\u30cc\u30eb\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.property_create_name_already_in_use=''{0}'' \u3068\u3044\u3046\u30d7\u30ed\u30d1\u30c6\u30a3\u540d\u306f\u3059\u3067\u306b\u4f7f\u308f\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.property_update_prop_not_found=''{0}'' \u3068\u4e00\u81f4\u3059\u308b\u30d7\u30ed\u30d1\u30c6\u30a3\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.property_change_datatype_err=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30e2\u30c7\u30eb\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u30c7\u30fc\u30bf\u578b\u306f\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.property_change_mandatory_opt_err=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30e2\u30c7\u30eb\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u5fc5\u9808\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.property_change_mandatory_enforced_opt_err=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30e2\u30c7\u30eb\u306e\u5fc5\u9808\u81ea\u52d5\u5165\u529b\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.property_change_multi_valued_opt_err=\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u30e2\u30c7\u30eb\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u306e\u8907\u6570\u5024\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002
# validation
cmm.rest_api.input_validation_err=''{0}'' \u306f\u6709\u52b9\u306a\u5024\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u6570\u5b57\u3001\u82f1\u5b57\u3001\u30cf\u30a4\u30d5\u30f3 (-)\u3001\u30a2\u30f3\u30c0\u30fc\u30b9\u30b3\u30a2 (_) \u3060\u3051\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002
cmm.rest_api.prefix_not_registered=URI ''{0}'' \u7528\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u540d\u524d\u7a7a\u9593\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002 \u30e2\u30c7\u30eb\u304c\u6709\u52b9\u5316\u3055\u308c\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002
cmm.rest_api.prefixed_qname_invalid=''{0}'' \u306f\u6709\u52b9\u306a\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u4ed8\u304d QName \u5024\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 {1}
cmm.rest_api.circular_dependency_err=\u5faa\u74b0\u4f9d\u5b58\u304c\u691c\u51fa\u3055\u308c\u307e\u3057\u305f\u3002 ''{0}'' \u306f\u3059\u3067\u306b ''{1}'' \u306b\u4f9d\u5b58\u3059\u308b\u30e2\u30c7\u30eb\u3067\u3042\u308b\u305f\u3081\u3001\u89aa\u3092\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' \u306f\u6709\u52b9\u306a\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u4ed8\u304d QName \u5f62\u5f0f\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u6709\u52b9\u306a\u5f62\u5f0f\u306f\u3001\u540d\u524d\u7a7a\u9593\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u3001\u30b3\u30ed\u30f3 (:)\u3001\u540d\u524d\u306e\u7d44\u307f\u5408\u308f\u305b\u3067\u3059\u3002\u4f8b: cm:content
# model import
cmm.rest_api.model.import_namespace_multiple_found=\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u306b\u5b9a\u7fa9\u3067\u304d\u308b\u540d\u524d\u7a7a\u9593\u306f 1 \u3064\u3060\u3051\u3067\u3059\u304c\u3001 ''{0}'' \u500b\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002
cmm.rest_api.model.import_namespace_undefined=\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u306b\u540d\u524d\u7a7a\u9593\u3092 1 \u3064\u5b9a\u7fa9\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
cmm.rest_api.model.import_associations_unsupported=\u3053\u306e\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u3067\u306f 'associations' \u8981\u7d20\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_overrides_unsupported=\u3053\u306e\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u3067\u306f 'overrides' \u8981\u7d20\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_mandatory_aspects_unsupported=\u3053\u306e\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u3067\u306f 'mandatory-aspects' \u8981\u7d20\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_archive_unsupported=\u3053\u306e\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u3067\u306f 'archive' \u8981\u7d20\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_includedInSuperTQ_unsupported=\u3053\u306e\u30ab\u30b9\u30bf\u30e0\u30e2\u30c7\u30eb\u3067\u306f 'includedInSuperTypeQuery' \u8981\u7d20\u3092\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_not_multi_part_req=\u30ea\u30af\u30a8\u30b9\u30c8\u306f\u30de\u30eb\u30c1\u30d1\u30fc\u30c8\u306e\u30d5\u30a9\u30fc\u30e0\u30c7\u30fc\u30bf\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_not_zip_format=''{0}'' \u306f\u6709\u52b9\u306a zip \u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_process_zip_file_failure=zip \u30d5\u30a1\u30a4\u30eb\u3092\u51e6\u7406\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.model.import_no_zip_file_uploaded=zip \u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.model.import_invalid_zip_package=\u3053\u306e zip \u30d5\u30a1\u30a4\u30eb\u306b 3 \u3064\u4ee5\u4e0a\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u542b\u3081\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 \u30e2\u30c7\u30eb\u30d5\u30a1\u30a4\u30eb\u3068\u62e1\u5f35\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u3092\u305d\u308c\u305e\u308c 1 \u3064\u305a\u3064\u542b\u3081\u308b\u3088\u3046\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' \u306f\u30e2\u30c7\u30eb\u30d5\u30a1\u30a4\u30eb\u307e\u305f\u306f Share \u62e1\u5f35\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_invalid_model_entry=''{0}'' \u306f\u6709\u52b9\u306a\u30e2\u30c7\u30eb\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' \u306f\u6709\u52b9\u306a Share \u62e1\u5f35\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002
cmm.rest_api.model.import_failure=\u30e2\u30c7\u30eb\u3092\u30a4\u30f3\u30dd\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
cmm.rest_api.model.import_process_ext_module_file_failure=Share \u62e1\u5f35\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u3092\u51e6\u7406\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=Modellnavn kan ikke v\u00e6re null.
cmm.rest_api.model_invalid=Ugyldig tilpasset modell.
cmm.rest_api.model_status_null=Modellstatus kan ikke v\u00e6re null.
cmm.rest_api.model_name_cannot_update=Modellnavnet kan ikke oppdateres.
cmm.rest_api.model_update_failure=Vi kan ikke oppdatere modellen.
cmm.rest_api.model_download_failure=Vi kan ikke opprette en nedlastingsnode.
cmm.rest_api.model_namespace_uri_null=Modellens URI for navneomr\u00e5det kan ikke v\u00e6re null.
cmm.rest_api.model_namespace_uri_invalid=URI for navneomr\u00e5det er ugyldig. Bruk kun bokstaver, tall og URI-tegn.
cmm.rest_api.model_namespace_prefix_null=Modellens prefiks for navneomr\u00e5det kan ikke v\u00e6re null.
# Type
cmm.rest_api.type_name_null=Type navn kan ikke v\u00e6re null.
cmm.rest_api.type_create_failure=Vi kan ikke opprette typen.
cmm.rest_api.type_update_failure=Vi kan ikke oppdatere typen.
cmm.rest_api.type_parent_cannot_update=Du kan ikke oppdatere typens overordnede i en aktiv, tilpasset modell.
cmm.rest_api.type_parent_not_exist=Du kan ikke angi typens overordnede som ''{0}'', fordi typen ''{0}'' finnes ikke.
cmm.rest_api.type_cannot_delete=En type i en aktiv modell kan ikke slettes.
cmm.rest_api.type_delete_failure=Vi kan ikke slette typen.
# Aspect
cmm.rest_api.aspect_name_null=Aspektnavn kan ikke v\u00e6re null.
cmm.rest_api.aspect_create_failure=Vi kan ikke opprette aspektet.
cmm.rest_api.aspect_update_failure=Vi kan ikke oppdatere aspektet.
cmm.rest_api.aspect_parent_cannot_update=Du kan ikke oppdatere det aspektets overordnede i en aktiv, tilpasset modell.
cmm.rest_api.aspect_parent_not_exist=Du kan ikke angi aspektets overordnede til ''{0}'', fordi aspektet ''{0}'' finnes ikke.
cmm.rest_api.aspect_cannot_delete=Et aspekt i en aktiv modell kan ikke slettes.
cmm.rest_api.aspect_delete_failure=Vi kan ikke slette aspektet.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=''{0}'' kan ikke slettes fordi ''{1}'' er avhengig av den.
# Constraint
cmm.rest_api.constraint_name_null=Restriksjonsnavn kan ikke v\u00e6re null.
cmm.rest_api.constraint_create_failure=Vi kan ikke opprette restriksjon.
cmm.rest_api.constraint_parameter_name_null=Restriksjonsparameternavn kan ikke v\u00e6re null.
cmm.rest_api.constraint_type_null=Tilpasset restriksjon m\u00e5 ha en 'type' attributt.
cmm.rest_api.constraint_ref_not_defined=Restriksjonsreferansen ''{0}'' defineres ikke av denne modellen.
cmm.rest_api.regex_constraint_invalid_expression=REGEX-uttrykket ''{0}'' er ikke gyldig.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' er ikke et gyldig ''dobbel'' verdi for MINMAX-parameteret ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=Maksimalverdien til MINMAX-restriksjonen m\u00e5 v\u00e6re st\u00f8rre enn null.
cmm.rest_api.minmax_constraint_invalid_use=MINMAX-restriksjon kan bare brukes med nummerisk datatype.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' er ikke et gyldig ''helt tall'' for LENGTH-parameteret ''{1}''.
cmm.rest_api.length_constraint_invalid_use=Kun LENGTH-restriksjonen kan brukes sammen med TEXT-, CONTENT- og MLTEXT-datatyper.
# Property
cmm.rest_api.property_name_null=Egenskapsnavn kan ikke v\u00e6re null.
cmm.rest_api.property_create_update_failure=Vi kan ikke opprette/oppdatere egenskap.
cmm.rest_api.property_delete_failure=Vi kan ikke slette egenskapen..
cmm.rest_api.property_datatype_invalid=''{0}'' er ikke gyldig datatypeformat. Et gyldig format skal best\u00e5 av prefiks for til navneomr\u00e5de, kolon og et navn, som f.eks: d:tekst.
cmm.rest_api.properties_empty_null=Egenskapene kan ikke v\u00e6re tomme eller null.
cmm.rest_api.property_create_name_already_in_use=Vi kan ikke opprette egenskapen fordi egenskapsnavnet ''{0}'' er allerede i bruk.
cmm.rest_api.property_update_prop_not_found=Vi kan ikke finne en egenskap som stemmer overens med ''{0}''.
cmm.rest_api.property_change_datatype_err=Du kan ikke endre datatypen til en egenskap i en aktiv modell.
cmm.rest_api.property_change_mandatory_opt_err=Du kan ikke endre det obligatoriske alternativet til en egenskap i en aktiv modell.
cmm.rest_api.property_change_mandatory_enforced_opt_err=Du kan ikke endre det obligatoriske, h\u00e5ndhevede alternativet til en egenskap i en aktiv modell.
cmm.rest_api.property_change_multi_valued_opt_err=Du kan ikke endre alternativet med flere verdier til en egenskap i en aktiv modell.
# validation
cmm.rest_api.input_validation_err=''{0}'' er ikke en gyldig verdi. Bruk kun tall, bokstaver, bindestreker (-) og understreking (_).
cmm.rest_api.prefix_not_registered=Det finnes ikke en prefiks for navneomr\u00e5det som er registrert for URI-en ''{0}''. Kontroller at modellen er aktiv.
cmm.rest_api.prefixed_qname_invalid=''{0}'' er ikke en gyldig forh\u00e5ndsbestemt QName-verdi. {1}
cmm.rest_api.circular_dependency_err=En det funnet en sirkul\u00e6r avhengighet. Du kan ikke angi overordnede ''{0}'' fordi dens modell er allerede avhengig av ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' er ikke et gyldig forh\u00e5ndsbestemt QName-format. Et gyldig format skal best\u00e5 av en prefiks for navneomr\u00e5det, et kolon og et navn, som f.eks: cm:innhold.
# model import
cmm.rest_api.model.import_namespace_multiple_found=Den tilpassede modellen kan bare ha ett navneomr\u00e5de. Vi fant ''{0}''.
cmm.rest_api.model.import_namespace_undefined=Den tilpassede modellen m\u00e5 definere et navneomr\u00e5de.
cmm.rest_api.model.import_associations_unsupported=Den tilpassede modellen st\u00f8tter ikke elementet 'associations'.
cmm.rest_api.model.import_overrides_unsupported=Den tilpassede modellen st\u00f8tter ikke elementet 'overrides'.
cmm.rest_api.model.import_mandatory_aspects_unsupported=Den tilpassed modellen st\u00f8tter ikke elementet 'mandatory-aspects'.
cmm.rest_api.model.import_archive_unsupported=Den tilpassede modellen st\u00f8tter ikke elementet 'archive'.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=Den tilpassede modellen st\u00f8tter ikke elementet 'includedInSuperTypeQuery'.
cmm.rest_api.model.import_not_multi_part_req=Foresp\u00f8rselen har data med flere deler.
cmm.rest_api.model.import_not_zip_format=''{0}'' er ikke gyldig zip-format.
cmm.rest_api.model.import_process_zip_file_failure=Vi kan ikke behandle zip-filen.
cmm.rest_api.model.import_no_zip_file_uploaded=Vi kan ikke laste opp zip-filen.
cmm.rest_api.model.import_invalid_zip_package=Zip-filen kan ikke ha flere enn to filer. Det skal v\u00e6re \u00e9n modellfil og \u00e9n utvidelsesmodulfil.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' er ikke en modell eller Share-utvidelsesmodulfil.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' er ikke en gyldig modellfil.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' er ikke en gyldig Share-utvidelsesmodulfil.
cmm.rest_api.model.import_failure=Vi kan ikke importere modellen.
cmm.rest_api.model.import_process_ext_module_file_failure=Vi kan ikke behandle Share-utvidelsesmodulfilen.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=Modelnaam kan niet null zijn.
cmm.rest_api.model_invalid=Ongeldig aangepast model.
cmm.rest_api.model_status_null=Modelstatus kan niet null zijn.
cmm.rest_api.model_name_cannot_update=U kunt de modelnaam niet bijwerken.
cmm.rest_api.model_update_failure=Kan het model niet bijwerken.
cmm.rest_api.model_download_failure=Kan geen downloadnode maken.
cmm.rest_api.model_namespace_uri_null=De modelnaamruimte-URI kan niet null zijn.
cmm.rest_api.model_namespace_uri_invalid=De naamruimte-URI is ongeldig. Gebruik alleen letters, cijfers en URI-tekens.
cmm.rest_api.model_namespace_prefix_null=Modelnaamruimtevoorvoegsel kan niet null zijn.
# Type
cmm.rest_api.type_name_null=Typenaam kan niet null zijn.
cmm.rest_api.type_create_failure=Kan het type niet maken.
cmm.rest_api.type_update_failure=Kan het type niet bijwerken.
cmm.rest_api.type_parent_cannot_update=U kunt het bovenliggende type van een type in een actief aangepast model niet bijwerken.
cmm.rest_api.type_parent_not_exist=U kunt het bovenliggende type van het type niet instellen op ''{0}'' omdat het type ''{0}'' niet bestaat.
cmm.rest_api.type_cannot_delete=U kunt een type in een actief model niet verwijderen.
cmm.rest_api.type_delete_failure=Kan het type niet verwijderen.
# Aspect
cmm.rest_api.aspect_name_null=Aspectnaam kan niet null zijn.
cmm.rest_api.aspect_create_failure=Kan het aspect niet maken.
cmm.rest_api.aspect_update_failure=Kan het aspect niet bijwerken.
cmm.rest_api.aspect_parent_cannot_update=U kunt het bovenliggende aspect van het aspect in een actief aangepast model niet bijwerken.
cmm.rest_api.aspect_parent_not_exist=U kunt het bovenliggende aspect van het aspect niet instellen op ''{0}'' omdat het aspect ''{0}'' niet bestaat.
cmm.rest_api.aspect_cannot_delete=U kunt een aspect in een actief model niet verwijderen.
cmm.rest_api.aspect_delete_failure=Kan het aspect niet verwijderen.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=U kunt ''{0}'' niet verwijderen omdat ''{1}'' hiervan afhankelijk is.
# Constraint
cmm.rest_api.constraint_name_null=Beperkingsnaam kan niet null zijn.
cmm.rest_api.constraint_create_failure=Kan beperking niet maken.
cmm.rest_api.constraint_parameter_name_null=Beperkingsparameter kan niet null zijn.
cmm.rest_api.constraint_type_null=Aangepaste beperking moet een 'type'-kenmerk hebben.
cmm.rest_api.constraint_ref_not_defined=Beperkingsverwijzing ''{0}'' wordt niet gedefinieerd door dit model.
cmm.rest_api.regex_constraint_invalid_expression=REGEX-expressie ''{0}'' is niet geldig.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' is geen geldige ''dubbele'' waarde voor de MINMAX-parameter ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=De maximale waarde van de MINMAX-beperking moet hoger zijn dan nul.
cmm.rest_api.minmax_constraint_invalid_use=MINMAX-beperking kan alleen worden gebruikt met een numeriek gegevenstype.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' is geen geldige ''integer''-waarde voor de LENGTH-parameter ''{1}''.
cmm.rest_api.length_constraint_invalid_use=U kunt de LENGTH-beperking alleen gebruiken met TEXT-, CONTENT- en MLTEXT-gegevenstypen.
# Property
cmm.rest_api.property_name_null=Eigenschapnaam kan niet null zijn.
cmm.rest_api.property_create_update_failure=Kan de eigenschap niet maken/bijwerken.
cmm.rest_api.property_delete_failure=Kan de eigenschap niet verwijderen.
cmm.rest_api.property_datatype_invalid=''{0}'' is geen geldige gegevenstype-indeling. Een geldige indeling moet bestaan uit een naamruimtevoorvoegsel, een dubbele punt en een naam, bijvoorbeeld: d:tekst.
cmm.rest_api.properties_empty_null=Eigenschappen kunnen niet leeg of null zijn.
cmm.rest_api.property_create_name_already_in_use=Kan de eigenschap niet maken omdat de eigenschapsnaam ''{0}'' al in gebruik is.
cmm.rest_api.property_update_prop_not_found=Kan geen eigenschap vinden dat overeenkomt met ''{0}''.
cmm.rest_api.property_change_datatype_err=U kunt het gegevenstype van een eigenschap in een actief model niet wijzigen.
cmm.rest_api.property_change_mandatory_opt_err=U kunt de verplichte optie van een eigenschap in een actief model niet wijzigen.
cmm.rest_api.property_change_mandatory_enforced_opt_err=U kunt de verplichte-afgedwongen optie van een eigenschap in een actief model niet wijzigen.
cmm.rest_api.property_change_multi_valued_opt_err=U kunt de meerwaardige optie van een eigenschap in een actief model niet wijzigen.
# validation
cmm.rest_api.input_validation_err=''{0}'' is geen geldige waarde. Gebruik alleen cijfers, letters, afbreekstreepjes (-) en onderstrepingstekens (_).
cmm.rest_api.prefix_not_registered=Er is geen naamruimtevoorvoegsel geregistreerd voor de URI ''{0}''. Controleer of het model actief is.
cmm.rest_api.prefixed_qname_invalid=''{0}'' is geen geldige waarde voor QName met voorvoegsel. {1}
cmm.rest_api.circular_dependency_err=Er is een circulaire afhankelijkheid vastgesteld. U kunt het bovenliggende element ''{0}'' niet instellen, omdat het bijbehorende model al afhankelijk is van ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' is geen geldige indeling voor QName met voorvoegsel. Een geldige indeling moet bestaan uit een naamruimtevoorvoegsel, een dubbele punt en een naam, bijvoorbeeld: cm:content.
# model import
cmm.rest_api.model.import_namespace_multiple_found=Het aangepaste model kan slechts \u00e9\u00e9n naamruimte hebben. ''{0}'' gevonden.
cmm.rest_api.model.import_namespace_undefined=Het aangepaste model moet een naamruimte defini\u00ebren.
cmm.rest_api.model.import_associations_unsupported=Het aangepaste model biedt geen ondersteuning voor het element 'associations'.
cmm.rest_api.model.import_overrides_unsupported=Het aangepaste model biedt geen ondersteuning voor het element 'overrides'.
cmm.rest_api.model.import_mandatory_aspects_unsupported=Het aangepaste model biedt geen ondersteuning voor het element 'mandatory-aspects'.
cmm.rest_api.model.import_archive_unsupported=Het aangepaste model biedt geen ondersteuning voor het element 'archive'.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=Het aangepaste model biedt geen ondersteuning voor het element 'includedInSuperTypeQuery'.
cmm.rest_api.model.import_not_multi_part_req=Aanvraag betreft geen meerdelige-formuliergegevens.
cmm.rest_api.model.import_not_zip_format=''{0}'' is geen geldig .zip-bestand.
cmm.rest_api.model.import_process_zip_file_failure=Kan het .zip-bestand niet verwerken.
cmm.rest_api.model.import_no_zip_file_uploaded=Kan het .zip-bestand niet uploaden.
cmm.rest_api.model.import_invalid_zip_package=Het .zip-bestand kan niet meer dan twee bestanden bevatten. Er moet \u00e9\u00e9n modelbestand en \u00e9\u00e9n extensiemodulebestand zijn.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' is geen modelbestand of een Share-extensiemodulebestand.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' is geen geldig modelbestand.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' is geen Share-extensiemodulebestand.
cmm.rest_api.model.import_failure=Kan het model niet importeren.
cmm.rest_api.model.import_process_ext_module_file_failure=Kan het Share-extensiemodulebestand niet verwerken.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=O nome do modelo n\u00e3o pode ser nulo.
cmm.rest_api.model_invalid=Modelo personalizado inv\u00e1lido.
cmm.rest_api.model_status_null=O status do modelo n\u00e3o pode ser nulo.
cmm.rest_api.model_name_cannot_update=N\u00e3o \u00e9 poss\u00edvel atualizar o nome do modelo.
cmm.rest_api.model_update_failure=N\u00e3o foi poss\u00edvel atualizar o modelo.
cmm.rest_api.model_download_failure=N\u00e3o foi poss\u00edvel criar um n\u00f3 de download.
cmm.rest_api.model_namespace_uri_null=O URI do espa\u00e7o de nomes do modelo n\u00e3o pode ser nulo.
cmm.rest_api.model_namespace_uri_invalid=O URI do espa\u00e7o de nomes \u00e9 inv\u00e1lido. Use apenas n\u00fameros, letras e caracteres URI.
cmm.rest_api.model_namespace_prefix_null=O prefixo do espa\u00e7o de nomes do modelo n\u00e3o pode ser nulo.
# Type
cmm.rest_api.type_name_null=O nome do tipo n\u00e3o pode ser nulo.
cmm.rest_api.type_create_failure=N\u00e3o foi poss\u00edvel criar o tipo.
cmm.rest_api.type_update_failure=N\u00e3o foi poss\u00edvel atualizar o tipo.
cmm.rest_api.type_parent_cannot_update=N\u00e3o \u00e9 poss\u00edvel atualizar o tipo principal em um modelo personalizado ativo.
cmm.rest_api.type_parent_not_exist=N\u00e3o \u00e9 poss\u00edvel configurar o tipo principal como ''{0}'', porque o tipo ''{0}'' n\u00e3o existe.
cmm.rest_api.type_cannot_delete=N\u00e3o \u00e9 poss\u00edvel excluir um tipo em um modelo ativo.
cmm.rest_api.type_delete_failure=N\u00e3o foi poss\u00edvel excluir o tipo.
# Aspect
cmm.rest_api.aspect_name_null=O nome do aspecto n\u00e3o pode ser nulo.
cmm.rest_api.aspect_create_failure=N\u00e3o foi poss\u00edvel criar o aspecto.
cmm.rest_api.aspect_update_failure=N\u00e3o foi poss\u00edvel atualizar o aspecto.
cmm.rest_api.aspect_parent_cannot_update=N\u00e3o \u00e9 poss\u00edvel atualizar o aspecto principal em um modelo personalizado ativo.
cmm.rest_api.aspect_parent_not_exist=N\u00e3o \u00e9 poss\u00edvel configurar o aspecto principal como ''{0}'', porque o aspecto ''{0}'' n\u00e3o existe.
cmm.rest_api.aspect_cannot_delete=N\u00e3o \u00e9 poss\u00edvel excluir um aspecto em um modelo ativo.
cmm.rest_api.aspect_delete_failure=N\u00e3o foi poss\u00edvel excluir o aspecto.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=N\u00e3o \u00e9 poss\u00edvel excluir ''{0}'', pois ''{1}'' depende dele.
# Constraint
cmm.rest_api.constraint_name_null=O nome da restri\u00e7\u00e3o n\u00e3o pode ser nulo.
cmm.rest_api.constraint_create_failure=N\u00e3o foi poss\u00edvel criar a restri\u00e7\u00e3o.
cmm.rest_api.constraint_parameter_name_null=O par\u00e2metro da restri\u00e7\u00e3o n\u00e3o pode ser nulo.
cmm.rest_api.constraint_type_null=Restri\u00e7\u00e3o personalizada deve conter um atributo de 'tipo'.
cmm.rest_api.constraint_ref_not_defined=A refer\u00eancia de restri\u00e7\u00e3o ''{0}'' n\u00e3o \u00e9 definida por este modelo.
cmm.rest_api.regex_constraint_invalid_expression=A express\u00e3o REGEX ''{0}'' n\u00e3o \u00e9 v\u00e1lida
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' n\u00e3o \u00e9 um valor ''duplo'' v\u00e1lido para o par\u00e2metro MINMAX ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=O valor m\u00e1ximo da restri\u00e7\u00e3o MINMAX deve ser maior que zero.
cmm.rest_api.minmax_constraint_invalid_use=A restri\u00e7\u00e3o MINMAX s\u00f3 pode ser usada com tipo de dados num\u00e9ricos.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' n\u00e3o \u00e9 um valor ''inteiro'' v\u00e1lido para o par\u00e2metro LENGTH ''{1}''.
cmm.rest_api.length_constraint_invalid_use=Voc\u00ea s\u00f3 pode usar a restri\u00e7\u00e3o LENGTH com tipos de dados TEXT, CONTENT e MLTEXT.
# Property
cmm.rest_api.property_name_null=O nome da propriedade n\u00e3o pode ser nulo.
cmm.rest_api.property_create_update_failure=N\u00e3o foi poss\u00edvel criar/atualizar a propriedade.
cmm.rest_api.property_delete_failure=N\u00e3o foi poss\u00edvel excluir a propriedade.
cmm.rest_api.property_datatype_invalid=''{0}'' n\u00e3o \u00e9 um formato de tipo de dados v\u00e1lido. Um formato v\u00e1lido deve conter um prefixo do espa\u00e7o de nomes, dois pontos e um nome, por exemplo: d:texto.
cmm.rest_api.properties_empty_null=As propriedades n\u00e3o podem estar em branco ou ser nulas.
cmm.rest_api.property_create_name_already_in_use=N\u00e3o foi poss\u00edvel criar a propriedade j\u00e1 que o nome da propriedade ''{0}'' j\u00e1 est\u00e1 em uso.
cmm.rest_api.property_update_prop_not_found=N\u00e3o foi poss\u00edvel encontrar uma propriedade que corresponda a ''{0}''.
cmm.rest_api.property_change_datatype_err=N\u00e3o \u00e9 poss\u00edvel alterar o tipo de dados de uma propriedade em um modelo ativo.
cmm.rest_api.property_change_mandatory_opt_err=N\u00e3o \u00e9 poss\u00edvel alterar a op\u00e7\u00e3o obrigat\u00f3ria de uma propriedade em um modelo ativo.
cmm.rest_api.property_change_mandatory_enforced_opt_err=N\u00e3o \u00e9 poss\u00edvel alterar a op\u00e7\u00e3o obrigat\u00f3ria e for\u00e7ada de uma propriedade em um modelo ativo.
cmm.rest_api.property_change_multi_valued_opt_err=N\u00e3o \u00e9 poss\u00edvel alterar a op\u00e7\u00e3o de multivalores de uma propriedade em um modelo ativo.
# validation
cmm.rest_api.input_validation_err=''{0}'' n\u00e3o \u00e9 um valor v\u00e1lido. Use apenas n\u00fameros, letras, h\u00edfen (-) e sublinhado (_).
cmm.rest_api.prefix_not_registered=N\u00e3o h\u00e1 um prefixo do espa\u00e7o de nomes registrado para o URI ''{0}''. Assegure-se de que o modelo esteja ativo.
cmm.rest_api.prefixed_qname_invalid=''{0}'' n\u00e3o \u00e9 um valor de QName com prefixo v\u00e1lido. {1}
cmm.rest_api.circular_dependency_err=Foi detectada uma depend\u00eancia circular. N\u00e3o \u00e9 poss\u00edvel configurar o principal ''{0}'', pois seu modelo j\u00e1 depende de ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' n\u00e3o \u00e9 um formato de QName com prefixo v\u00e1lido. Um formato v\u00e1lido deve conter um prefixo do espa\u00e7o de nomes, dois pontos e um nome, por exemplo: cm:conte\u00fado.
# model import
cmm.rest_api.model.import_namespace_multiple_found=O modelo personalizado s\u00f3 pode ter um espa\u00e7o de nomes. Encontramos ''{0}''.
cmm.rest_api.model.import_namespace_undefined=O modelo personalizado deve definir um espa\u00e7o de nomes.
cmm.rest_api.model.import_associations_unsupported=O modelo personalizado n\u00e3o suporta o elemento 'associations'.
cmm.rest_api.model.import_overrides_unsupported=O modelo personalizado n\u00e3o suporta o elemento 'overrides'.
cmm.rest_api.model.import_mandatory_aspects_unsupported=O modelo personalizado n\u00e3o suporta o elemento 'mandatory-aspects'.
cmm.rest_api.model.import_archive_unsupported=O modelo personalizado n\u00e3o suporta o elemento 'archive'.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=O modelo personalizado n\u00e3o suporta o elemento 'includedInSuperTypeQuery'.
cmm.rest_api.model.import_not_multi_part_req=A solicita\u00e7\u00e3o n\u00e3o \u00e9 um formul\u00e1rio de dados de m\u00faltiplas partes.
cmm.rest_api.model.import_not_zip_format=''{0}'' n\u00e3o \u00e9 um arquivo zip v\u00e1lido.
cmm.rest_api.model.import_process_zip_file_failure=N\u00e3o foi poss\u00edvel processar o arquivo zip.
cmm.rest_api.model.import_no_zip_file_uploaded=N\u00e3o foi poss\u00edvel carregar o arquivo zip.
cmm.rest_api.model.import_invalid_zip_package=O arquivo zip n\u00e3o pode conter mais do que dois arquivos. Deve existir um arquivo Modelo e um arquivo de m\u00f3dulo Extens\u00e3o.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' n\u00e3o \u00e9 um modelo ou arquivo de m\u00f3dulo de extens\u00e3o Share.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' n\u00e3o \u00e9 um arquivo modelo v\u00e1lido.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' n\u00e3o \u00e9 um arquivo de m\u00f3dulo de extens\u00e3o Share v\u00e1lido.
cmm.rest_api.model.import_failure=N\u00e3o foi poss\u00edvel importar o modelo.
cmm.rest_api.model.import_process_ext_module_file_failure=N\u00e3o foi poss\u00edvel processar o arquivo de m\u00f3dulo de extens\u00e3o Share.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=\u0418\u043c\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.model_invalid=\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0430\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c.
cmm.rest_api.model_status_null=\u0421\u0442\u0430\u0442\u0443\u0441 \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.model_name_cannot_update=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043c\u044f \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.model_update_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043c\u044f \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.model_download_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u0437\u0435\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.
cmm.rest_api.model_namespace_uri_null=URI \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.model_namespace_uri_invalid=\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 URI \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0443\u043a\u0432\u044b, \u0446\u0438\u0444\u0440\u044b \u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u044b URI.
cmm.rest_api.model_namespace_prefix_null=\u041f\u0440\u0435\u0444\u0438\u043a\u0441 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
# Type
cmm.rest_api.type_name_null=\u0418\u043c\u044f \u0442\u0438\u043f\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.type_create_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0438\u043f.
cmm.rest_api.type_update_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u0438\u043f.
cmm.rest_api.type_parent_cannot_update=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0442\u0438\u043f \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.type_parent_not_exist=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c ''{0}'' \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0442\u0438\u043f\u0430: \u0442\u0438\u043f ''{0}'' \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
cmm.rest_api.type_cannot_delete=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0438\u043f \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.type_delete_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0438\u043f.
# Aspect
cmm.rest_api.aspect_name_null=\u0418\u043c\u044f \u0430\u0441\u043f\u0435\u043a\u0442\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.aspect_create_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442.
cmm.rest_api.aspect_update_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442.
cmm.rest_api.aspect_parent_cannot_update=\u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.aspect_parent_not_exist=\u041d\u0435\u043b\u044c\u0437\u044f \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c ''{0}'' \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0430\u0441\u043f\u0435\u043a\u0442\u0430: \u0430\u0441\u043f\u0435\u043a\u0442 ''{0}'' \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
cmm.rest_api.aspect_cannot_delete=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442 \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.aspect_delete_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442.
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c ''{0}'', \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 ''{1}'' \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.
# Constraint
cmm.rest_api.constraint_name_null=\u0418\u043c\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.constraint_create_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435.
cmm.rest_api.constraint_parameter_name_null=\u0418\u043c\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.constraint_type_null=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 'type'.
cmm.rest_api.constraint_ref_not_defined=\u0414\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 ''{0}''.
cmm.rest_api.regex_constraint_invalid_expression=\u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 REGEX ''{0}'' \u043d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e.
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0438 \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 MINMAX ''{1}''.
cmm.rest_api.minmax_constraint_invalid_max_value=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f MINMAX \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0443\u043b\u044f.
cmm.rest_api.minmax_constraint_invalid_use=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 MINMAX \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445.
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0446\u0435\u043b\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 LENGTH ''{1}''.
cmm.rest_api.length_constraint_invalid_use=\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 LENGTH \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 TEXT, CONTENT \u0438 MLTEXT.
# Property
cmm.rest_api.property_name_null=\u0418\u043c\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c.
cmm.rest_api.property_create_update_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c/\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e.
cmm.rest_api.property_delete_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e.
cmm.rest_api.property_datatype_invalid=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c \u0442\u0438\u043f\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d, \u0434\u0432\u043e\u0435\u0442\u043e\u0447\u0438\u044f \u0438 \u0438\u043c\u0435\u043d\u0438. \u041f\u0440\u0438\u043c\u0435\u0440: d:text.
cmm.rest_api.properties_empty_null=\u0414\u043b\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u0438\u043b\u0438 \u043d\u0443\u043b\u0435\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.
cmm.rest_api.property_create_name_already_in_use=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e: \u0438\u043c\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 ''{0}'' \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f.
cmm.rest_api.property_update_prop_not_found=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 ''{0}''.
cmm.rest_api.property_change_datatype_err=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.property_change_mandatory_opt_err=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.property_change_mandatory_enforced_opt_err=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (\u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439) \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.property_change_multi_valued_opt_err=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043c\u043d\u043e\u0433\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0441\u0442\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438.
# validation
cmm.rest_api.input_validation_err=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0438\u0441\u043b\u0430, \u0431\u0443\u043a\u0432\u044b, \u0434\u0435\u0444\u0438\u0441\u044b (-) \u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u044f (_).
cmm.rest_api.prefix_not_registered=\u0414\u043b\u044f URI ''{0}'' \u043d\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u0430.
cmm.rest_api.prefixed_qname_invalid=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c QName \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c. {1}
cmm.rest_api.circular_dependency_err=\u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0430 \u0446\u0438\u043a\u043b\u0438\u0447\u043d\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c. \u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 ''{0}'', \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0443\u0436\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 ''{1}''.
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c QName \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c. \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043c\u0435\u043d, \u0434\u0432\u043e\u0435\u0442\u043e\u0447\u0438\u044f \u0438 \u0438\u043c\u0435\u043d\u0438. \u041f\u0440\u0438\u043c\u0435\u0440: cm:content.
# model import
cmm.rest_api.model.import_namespace_multiple_found=\u0423 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0438\u043c\u0435\u043d. \u041e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u043e: ''{0}''.
cmm.rest_api.model.import_namespace_undefined=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0438\u043c\u0435\u043d.
cmm.rest_api.model.import_associations_unsupported=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 'associations'.
cmm.rest_api.model.import_overrides_unsupported=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 'overrides'.
cmm.rest_api.model.import_mandatory_aspects_unsupported=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 'mandatory-aspects'.
cmm.rest_api.model.import_archive_unsupported=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 'archive'.
cmm.rest_api.model.import_includedInSuperTQ_unsupported=\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 'includedInSuperTypeQuery'.
cmm.rest_api.model.import_not_multi_part_req=\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b.
cmm.rest_api.model.import_not_zip_format=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c zip-\u0444\u0430\u0439\u043b\u043e\u043c.
cmm.rest_api.model.import_process_zip_file_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c zip-\u0444\u0430\u0439\u043b.
cmm.rest_api.model.import_no_zip_file_uploaded=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c zip-\u0444\u0430\u0439\u043b.
cmm.rest_api.model.import_invalid_zip_package=zip-\u0444\u0430\u0439\u043b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0434\u0432\u0443\u0445 \u0444\u0430\u0439\u043b\u043e\u0432. \u0414\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b \u043c\u043e\u0434\u0443\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438 \u0438\u043b\u0438 \u0444\u0430\u0439\u043b\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.
cmm.rest_api.model.import_invalid_model_entry=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u043e\u043c \u043c\u043e\u0434\u0435\u043b\u0438.
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.
cmm.rest_api.model.import_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u044c.
cmm.rest_api.model.import_process_ext_module_file_failure=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u043c\u043e\u0434\u0443\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.

View File

@@ -0,0 +1,78 @@
# Messages returned by the CMM Rest API
# Model
cmm.rest_api.model_name_null=\u6a21\u578b\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.model_invalid=\u81ea\u5b9a\u4e49\u6a21\u578b\u65e0\u6548\u3002
cmm.rest_api.model_status_null=\u6a21\u578b\u72b6\u6001\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.model_name_cannot_update=\u60a8\u65e0\u6cd5\u66f4\u65b0\u6a21\u578b\u540d\u79f0\u3002
cmm.rest_api.model_update_failure=\u6211\u4eec\u65e0\u6cd5\u66f4\u65b0\u6a21\u578b\u3002
cmm.rest_api.model_download_failure=\u6211\u4eec\u65e0\u6cd5\u521b\u5efa\u4e0b\u8f7d\u8282\u70b9\u3002
cmm.rest_api.model_namespace_uri_null=\u6a21\u578b\u547d\u540d\u7a7a\u95f4 URI \u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.model_namespace_uri_invalid=\u547d\u540d\u7a7a\u95f4 URI \u65e0\u6548\u3002 \u4ec5\u53ef\u4f7f\u7528\u5b57\u6bcd\u3001\u6570\u5b57\u548c URI \u5b57\u7b26\u3002
cmm.rest_api.model_namespace_prefix_null=\u6a21\u578b\u547d\u540d\u7a7a\u95f4\u524d\u7f00\u4e0d\u80fd\u4e3a\u7a7a\u3002
# Type
cmm.rest_api.type_name_null=\u7c7b\u578b\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.type_create_failure=\u6211\u4eec\u65e0\u6cd5\u521b\u5efa\u7c7b\u578b\u3002
cmm.rest_api.type_update_failure=\u6211\u4eec\u65e0\u6cd5\u66f4\u65b0\u7c7b\u578b\u3002
cmm.rest_api.type_parent_cannot_update=\u60a8\u65e0\u6cd5\u5728\u6d3b\u8dc3\u7684\u81ea\u5b9a\u4e49\u6a21\u578b\u4e2d\u66f4\u65b0\u7c7b\u578b\u7684\u7236\u7ea7\u7c7b\u578b\u3002
cmm.rest_api.type_parent_not_exist=\u60a8\u65e0\u6cd5\u5c06\u7c7b\u578b\u7684\u7236\u7ea7\u7c7b\u578b\u8bbe\u7f6e\u4e3a ''{0}''\uff0c\u56e0\u4e3a\u7c7b\u578b ''{0}'' \u4e0d\u5b58\u5728\u3002
cmm.rest_api.type_cannot_delete=\u60a8\u65e0\u6cd5\u5220\u9664\u6d3b\u8dc3\u6a21\u578b\u4e2d\u7684\u7c7b\u578b\u3002
cmm.rest_api.type_delete_failure=\u6211\u4eec\u65e0\u6cd5\u5220\u9664\u7c7b\u578b\u3002
# Aspect
cmm.rest_api.aspect_name_null=\u5207\u9762\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.aspect_create_failure=\u6211\u4eec\u65e0\u6cd5\u521b\u5efa\u5207\u9762\u3002
cmm.rest_api.aspect_update_failure=\u6211\u4eec\u65e0\u6cd5\u66f4\u65b0\u5207\u9762\u3002
cmm.rest_api.aspect_parent_cannot_update=\u60a8\u65e0\u6cd5\u5728\u6d3b\u8dc3\u7684\u81ea\u5b9a\u4e49\u6a21\u578b\u4e2d\u66f4\u65b0\u5207\u9762\u7684\u7236\u7ea7\u5207\u9762\u3002
cmm.rest_api.aspect_parent_not_exist=\u60a8\u65e0\u6cd5\u5c06\u5207\u9762\u7684\u7236\u7ea7\u5207\u9762\u8bbe\u7f6e\u4e3a ''{0}''\uff0c\u56e0\u4e3a\u5207\u9762 ''{0}'' \u4e0d\u5b58\u5728\u3002
cmm.rest_api.aspect_cannot_delete=\u60a8\u65e0\u6cd5\u5728\u6d3b\u8dc3\u6a21\u578b\u4e2d\u5220\u9664\u5207\u9762\u3002
cmm.rest_api.aspect_delete_failure=\u6211\u4eec\u65e0\u6cd5\u5220\u9664\u5207\u9762\u3002
# TypeAspect
cmm.rest_api.aspect_type_cannot_delete=\u60a8\u65e0\u6cd5\u5220\u9664 ''{0}''\uff0c\u56e0\u4e3a ''{1}'' \u4f9d\u8d56\u4e8e\u5b83\u3002
# Constraint
cmm.rest_api.constraint_name_null=\u7ea6\u675f\u6761\u4ef6\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.constraint_create_failure=\u6211\u4eec\u65e0\u6cd5\u521b\u5efa\u7ea6\u675f\u6761\u4ef6\u3002
cmm.rest_api.constraint_parameter_name_null=\u7ea6\u675f\u6761\u4ef6\u53c2\u6570\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.constraint_type_null=\u81ea\u5b9a\u4e49\u7ea6\u675f\u6761\u4ef6\u5fc5\u987b\u6709 '\u7c7b\u578b' \u5c5e\u6027\u3002
cmm.rest_api.constraint_ref_not_defined=\u6b64\u6a21\u578b\u672a\u5b9a\u4e49\u7ea6\u675f\u6761\u4ef6\u5f15\u7528 ''{0}''\u3002
cmm.rest_api.regex_constraint_invalid_expression=REGEX \u8868\u8fbe\u5f0f ''{0}'' \u65e0\u6548\u3002
cmm.rest_api.minmax_constraint_invalid_parameter=''{0}'' \u4e0d\u662f MINMAX \u53c2\u6570 ''{1}'' \u7684\u6709\u6548 ''\u53cc\u7cbe\u5ea6'' \u503c\u3002
cmm.rest_api.minmax_constraint_invalid_max_value=MINMAX \u7ea6\u675f\u6761\u4ef6\u7684\u6700\u5927\u503c\u5fc5\u987b\u5927\u4e8e\u96f6\u3002
cmm.rest_api.minmax_constraint_invalid_use=MINMAX \u7ea6\u675f\u6761\u4ef6\u53ea\u80fd\u4e0e\u6570\u5b57\u578b\u6570\u636e\u7ed3\u5408\u4f7f\u7528\u3002
cmm.rest_api.length_constraint_invalid_parameter=''{0}'' \u4e0d\u662f LENGTH \u53c2\u6570 ''{1}'' \u7684\u6709\u6548 ''\u6574\u6570'' \u503c\u3002
cmm.rest_api.length_constraint_invalid_use=\u60a8\u53ea\u80fd\u5c06 LENGTH \u7ea6\u675f\u6761\u4ef6\u4e0e TEXT\u3001CONTENT \u548c MLTEXT \u7c7b\u578b\u6570\u636e\u7ed3\u5408\u4f7f\u7528\u3002
# Property
cmm.rest_api.property_name_null=\u5c5e\u6027\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.property_create_update_failure=\u6211\u4eec\u65e0\u6cd5\u521b\u5efa/\u66f4\u65b0\u5c5e\u6027\u3002
cmm.rest_api.property_delete_failure=\u6211\u4eec\u65e0\u6cd5\u5220\u9664\u5c5e\u6027\u3002
cmm.rest_api.property_datatype_invalid=''{0}'' \u4e0d\u662f\u6709\u6548\u7684\u6570\u636e\u7c7b\u578b\u683c\u5f0f\u3002 \u6709\u6548\u7684\u683c\u5f0f\u5e94\u5305\u542b\u547d\u540d\u7a7a\u95f4\u524d\u7f00\u3001\u5192\u53f7\u548c\u540d\u79f0\uff0c\u4f8b\u5982\uff1ad:text\u3002
cmm.rest_api.properties_empty_null=\u5c5e\u6027\u4e0d\u80fd\u4e3a\u7a7a\u3002
cmm.rest_api.property_create_name_already_in_use=\u6211\u4eec\u65e0\u6cd5\u521b\u5efa\u5c5e\u6027\uff0c\u56e0\u4e3a\u5c5e\u6027\u540d\u79f0 ''{0}''\u5df2\u5b58\u5728\u3002
cmm.rest_api.property_update_prop_not_found=\u6211\u4eec\u65e0\u6cd5\u627e\u5230\u4e0e ''{0}'' \u5339\u914d\u7684\u5c5e\u6027\u3002
cmm.rest_api.property_change_datatype_err=\u60a8\u65e0\u6cd5\u66f4\u6539\u6d3b\u8dc3\u6a21\u578b\u4e2d\u5c5e\u6027\u7684\u6570\u636e\u7c7b\u578b\u3002
cmm.rest_api.property_change_mandatory_opt_err=\u60a8\u65e0\u6cd5\u66f4\u6539\u6d3b\u8dc3\u6a21\u578b\u4e2d\u5c5e\u6027\u7684\u5f3a\u5236\u9009\u9879\u3002
cmm.rest_api.property_change_mandatory_enforced_opt_err=\u60a8\u65e0\u6cd5\u66f4\u6539\u6d3b\u8dc3\u6a21\u578b\u4e2d\u5c5e\u6027\u7684\u5f3a\u5236\u6267\u884c\u9009\u9879\u3002
cmm.rest_api.property_change_multi_valued_opt_err=\u60a8\u65e0\u6cd5\u66f4\u6539\u6d3b\u8dc3\u6a21\u578b\u4e2d\u5c5e\u6027\u7684\u591a\u503c\u9009\u9879\u3002
# validation
cmm.rest_api.input_validation_err=''{0}'' \u4e0d\u662f\u6709\u6548\u503c\u3002 \u4ec5\u53ef\u4f7f\u7528\u6570\u5b57\u3001\u5b57\u6bcd\u3001\u8fde\u5b57\u7b26 (-) \u548c\u4e0b\u5212\u7ebf (_)\u3002
cmm.rest_api.prefix_not_registered=\u6ca1\u6709\u4e3a URI ''{0}'' \u6ce8\u518c\u547d\u540d\u7a7a\u95f4\u524d\u7f00\u3002 \u786e\u4fdd\u6a21\u578b\u4e3a\u6d3b\u8dc3\u3002
cmm.rest_api.prefixed_qname_invalid=''{0}'' \u4e0d\u662f\u52a0\u524d\u7f00\u7684\u6709\u6548 QName \u503c\u3002 {1}
cmm.rest_api.circular_dependency_err=\u68c0\u6d4b\u5230\u5faa\u73af\u4f9d\u5b58\u5173\u7cfb\u3002 \u60a8\u65e0\u6cd5\u8bbe\u7f6e\u7236\u7ea7 ''{0}''\uff0c\u56e0\u4e3a\u5b83\u7684\u6a21\u578b\u5df2\u7ecf\u4f9d\u8d56\u4e8e ''{1}''\u3002
cmm.rest_api.prefixed_qname_invalid_format=''{0}'' \u4e0d\u662f\u52a0\u524d\u7f00\u7684\u6709\u6548 QName \u683c\u5f0f\u3002 \u6709\u6548\u683c\u5f0f\u5e94\u5305\u542b\u547d\u540d\u7a7a\u95f4\u524d\u7f00\u3001\u5192\u53f7\u548c\u540d\u79f0\uff0c\u4f8b\u5982\uff1acm:content\u3002
# model import
cmm.rest_api.model.import_namespace_multiple_found=\u81ea\u5b9a\u4e49\u6a21\u578b\u53ea\u80fd\u6709\u4e00\u4e2a\u547d\u540d\u7a7a\u95f4\u3002 \u6211\u4eec\u627e\u5230 ''{0}''\u3002
cmm.rest_api.model.import_namespace_undefined=\u81ea\u5b9a\u4e49\u6a21\u578b\u5fc5\u987b\u5b9a\u4e49\u4e00\u4e2a\u547d\u540d\u7a7a\u95f4\u3002
cmm.rest_api.model.import_associations_unsupported=\u81ea\u5b9a\u4e49\u6a21\u578b\u4e0d\u652f\u6301 'associations' \u5143\u7d20\u3002
cmm.rest_api.model.import_overrides_unsupported=\u81ea\u5b9a\u4e49\u6a21\u578b\u4e0d\u652f\u6301 'overrides' \u5143\u7d20\u3002
cmm.rest_api.model.import_mandatory_aspects_unsupported=\u81ea\u5b9a\u4e49\u6a21\u578b\u4e0d\u652f\u6301 'mandatory-aspects' \u5143\u7d20\u3002
cmm.rest_api.model.import_archive_unsupported=\u81ea\u5b9a\u4e49\u6a21\u578b\u4e0d\u652f\u6301 'archive' \u5143\u7d20\u3002
cmm.rest_api.model.import_includedInSuperTQ_unsupported=\u81ea\u5b9a\u4e49\u6a21\u578b\u4e0d\u652f\u6301 'includedInSuperTypeQuery' \u5143\u7d20\u3002
cmm.rest_api.model.import_not_multi_part_req=\u8bf7\u6c42\u4e0d\u662f\u591a\u90e8\u5206\u7ec4\u6210\u6570\u636e\u3002
cmm.rest_api.model.import_not_zip_format=''{0}'' \u4e0d\u662f\u6709\u6548\u7684 zip \u6587\u4ef6\u3002
cmm.rest_api.model.import_process_zip_file_failure=\u6211\u4eec\u65e0\u6cd5\u5904\u7406 zip \u6587\u4ef6\u3002
cmm.rest_api.model.import_no_zip_file_uploaded=\u6211\u4eec\u65e0\u6cd5\u4e0a\u4f20 zip \u6587\u4ef6\u3002
cmm.rest_api.model.import_invalid_zip_package=zip \u6587\u4ef6\u5305\u542b\u7684\u6587\u4ef6\u4e0d\u80fd\u8d85\u8fc7\u4e24\u4e2a\u3002 \u5b83\u4eec\u5e94\u8be5\u4e3a\u4e00\u4e2a\u6a21\u578b\u6587\u4ef6\u548c\u4e00\u4e2a\u6269\u5c55\u6a21\u5757\u6587\u4ef6\u3002
cmm.rest_api.model.import_invalid_zip_entry_format=''{0}'' \u4e0d\u662f\u6a21\u578b\u6216\u5171\u4eab\u6269\u5c55\u6a21\u5757\u6587\u4ef6\u3002
cmm.rest_api.model.import_invalid_model_entry=''{0}'' \u4e0d\u662f\u6709\u6548\u7684\u6a21\u578b\u6587\u4ef6\u3002
cmm.rest_api.model.import_invalid_ext_module_entry=''{0}'' \u4e0d\u662f\u6709\u6548\u7684\u5171\u4eab\u6269\u5c55\u6a21\u5757\u6587\u4ef6\u3002
cmm.rest_api.model.import_failure=\u6211\u4eec\u65e0\u6cd5\u5bfc\u5165\u6a21\u578b\u3002
cmm.rest_api.model.import_process_ext_module_file_failure=\u6211\u4eec\u65e0\u6cd5\u5904\u7406\u5171\u4eab\u6269\u5c55\u6a21\u5757\u6587\u4ef6\u3002

View File

@@ -102,6 +102,7 @@
<property name="resourceBundles"> <property name="resourceBundles">
<list> <list>
<value>alfresco.messages.rest-framework-messages</value> <value>alfresco.messages.rest-framework-messages</value>
<value>alfresco.messages.custommodel-restapi-messages</value>
</list> </list>
</property> </property>
</bean> </bean>
@@ -937,4 +938,50 @@
<bean class="org.alfresco.rest.workflow.api.tasks.TaskItemsRelation"> <bean class="org.alfresco.rest.workflow.api.tasks.TaskItemsRelation">
<property name="tasks" ref="Tasks"/> <property name="tasks" ref="Tasks"/>
</bean> </bean>
<!-- -->
<!-- CMM REST API -->
<!-- -->
<bean id="customModels" class="org.alfresco.rest.api.impl.CustomModelsImpl">
<property name="customModelService" ref="customModelService" />
<property name="dictionaryService" ref="dictionaryService"/>
<property name="personService" ref="personService"/>
<property name="nodeService" ref="nodeService"/>
<property name="namespaceService" ref="namespaceService"/>
<property name="valueDataTypeValidator" ref="valueDataTypeValidator"/>
</bean>
<bean id="CustomModels" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.CustomModels</value>
</property>
<property name="target">
<ref bean="customModels" />
</property>
<property name="interceptorNames">
<list>
<idref bean="legacyExceptionInterceptor" />
</list>
</property>
</bean>
<bean class="org.alfresco.rest.api.cmm.CustomModelEntityResource">
<property name="customModels" ref="CustomModels" />
</bean>
<bean class="org.alfresco.rest.api.cmm.CustomModelTypesRelation">
<property name="customModels" ref="CustomModels" />
</bean>
<bean class="org.alfresco.rest.api.cmm.CustomModelAspectsRelation">
<property name="customModels" ref="CustomModels" />
</bean>
<bean class="org.alfresco.rest.api.cmm.CustomModelConstraintRelation">
<property name="customModels" ref="CustomModels" />
</bean>
<bean class="org.alfresco.rest.api.cmm.CustomModelDownloadRelation">
<property name="customModels" ref="CustomModels" />
</bean>
</beans> </beans>

View File

@@ -0,0 +1,20 @@
<webscript>
<shortname>Custom Model Upload</shortname>
<description>
<![CDATA[
Upload custom model and its associated share extension module as a zip file
http://<host>:<port>/alfresco/service/api/cmm/upload
<br />
Notes:
- user must be an Admin or a member of the ALFRESCO_MODEL_ADMINISTRATORS group
]]>
</description>
<url>/api/cmm/upload</url>
<format default="json"/>
<authentication>user</authentication>
<transaction>required</transaction>
<lifecycle>internal</lifecycle>
</webscript>

View File

@@ -0,0 +1,19 @@
<html>
<head>
<title>Upload Custom Model Failure</title>
</head>
<body>
<#if (args.failure!"")?matches("^[\\w\\d\\._]+$")>
<script type="text/javascript">
${args.failure?js_string}({
status: {
"code" : ${status.code?html},
"name" : "${status.codeName?json_string}",
"description" : "${status.codeDescription?json_string}"
},
message: "${status.message?json_string}"
});
</script>
</#if>
</body>
</html>

View File

@@ -0,0 +1,16 @@
<#escape x as jsonUtils.encodeJSONString(x)>
{
<#if importedModelName??>
"modelName": "${importedModelName}",
</#if>
<#if shareExtXMLFragment??>
"shareExtModule": "${shareExtXMLFragment}",
</#if>
"status":
{
"code": 200,
"name": "OK",
"description": "Model uploaded successfully"
}
}
</#escape>

View File

@@ -1856,5 +1856,12 @@
<property name="siteService" ref="SiteService" /> <property name="siteService" ref="SiteService" />
<property name="documentLinkService" ref="DocumentLinkService" /> <property name="documentLinkService" ref="DocumentLinkService" />
</bean> </bean>
<!-- CMM - Custom model import API -->
<bean id="webscript.org.alfresco.repository.custommodel.cmm-upload.post"
class="org.alfresco.repo.web.scripts.custommodel.CustomModelUploadPost"
parent="webscript">
<property name="customModels" ref="CustomModels" />
<property name="customModelService" ref="customModelService" />
</bean>
</beans> </beans>

View File

@@ -0,0 +1,306 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.web.scripts.custommodel;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import javax.xml.parsers.DocumentBuilder;
import org.alfresco.repo.dictionary.CustomModelServiceImpl;
import org.alfresco.repo.dictionary.M2Model;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.rest.api.CustomModels;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.framework.core.exceptions.ConstraintViolatedException;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.rest.framework.core.exceptions.PermissionDeniedException;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.cmr.dictionary.DictionaryException;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.XMLUtil;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.servlet.FormData;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* Custom model upload POST. This class is the controller for the
* "cmm-upload.post" web scripts.
*
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelUploadPost extends DeclarativeWebScript
{
private static final String SHARE_EXT_MODULE_ROOT_ELEMENT = "module";
private static final String TEMP_FILE_PREFIX = "cmmExport";
private static final String TEMP_FILE_SUFFIX = ".zip";
private static final int BUFFER_SIZE = 10 * 1024;
private CustomModels customModels;
private CustomModelService customModelService;
public void setCustomModels(CustomModels customModels)
{
this.customModels = customModels;
}
public void setCustomModelService(CustomModelService customModelService)
{
this.customModelService = customModelService;
}
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
{
if (!customModelService.isModelAdmin(AuthenticationUtil.getFullyAuthenticatedUser()))
{
throw new WebScriptException(Status.STATUS_FORBIDDEN, PermissionDeniedException.DEFAULT_MESSAGE_ID);
}
FormData formData = (FormData) req.parseContent();
if (formData == null || !formData.getIsMultiPart())
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_not_multi_part_req");
}
ImportResult resultData = null;
boolean processed = false;
for (FormData.FormField field : formData.getFields())
{
if (field.getIsFile())
{
final String fileName = field.getFilename();
File tempFile = createTempFile(field.getInputStream());
try (ZipFile zipFile = new ZipFile(tempFile, StandardCharsets.UTF_8))
{
resultData = processUpload(zipFile, field.getFilename());
}
catch (ZipException ze)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_not_zip_format", new Object[] { fileName });
}
catch (IOException io)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "cmm.rest_api.model.import_process_zip_file_failure", io);
}
finally
{
// now the import is done, delete the temp file
tempFile.delete();
}
processed = true;
break;
}
}
if (!processed)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_no_zip_file_uploaded");
}
// If we get here, then importing the custom model didn't throw any exceptions.
Map<String, Object> model = new HashMap<>(2);
model.put("importedModelName", resultData.getImportedModelName());
model.put("shareExtXMLFragment", resultData.getShareExtXMLFragment());
return model;
}
protected File createTempFile(InputStream inputStream)
{
try
{
File tempFile = TempFileProvider.createTempFile(inputStream, TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
return tempFile;
}
catch (Exception ex)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "cmm.rest_api.model.import_process_zip_file_failure", ex);
}
}
protected ImportResult processUpload(ZipFile zipFile, String filename) throws IOException
{
if (zipFile.size() > 2)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_invalid_zip_package");
}
CustomModel customModel = null;
String shareExtModule = null;
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
if (!entry.isDirectory())
{
final String entryName = entry.getName();
try (InputStream input = new BufferedInputStream(zipFile.getInputStream(entry), BUFFER_SIZE))
{
if (!(entryName.endsWith(CustomModelServiceImpl.SHARE_EXT_MODULE_SUFFIX)) && customModel == null)
{
try
{
M2Model m2Model = M2Model.createModel(input);
customModel = importModel(m2Model);
}
catch (DictionaryException ex)
{
if (shareExtModule == null)
{
// Get the input stream again, as the zip file doesn't support reset.
try (InputStream moduleInputStream = new BufferedInputStream(zipFile.getInputStream(entry), BUFFER_SIZE))
{
shareExtModule = getExtensionModule(moduleInputStream, entryName);
}
if (shareExtModule == null)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_invalid_zip_entry_format", new Object[] { entryName });
}
}
else
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_invalid_model_entry", new Object[] { entryName });
}
}
}
else
{
shareExtModule = getExtensionModule(input, entryName);
if (shareExtModule == null)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_invalid_ext_module_entry", new Object[] { entryName });
}
}
}
}
}
return new ImportResult(customModel, shareExtModule);
}
protected CustomModel importModel(M2Model m2Model)
{
CustomModel model = null;
try
{
model = customModels.createCustomModel(m2Model);
}
catch (Exception ex)
{
int statusCode;
if (ex instanceof ConstraintViolatedException)
{
statusCode = Status.STATUS_CONFLICT;
}
else if (ex instanceof InvalidArgumentException)
{
statusCode = Status.STATUS_BAD_REQUEST;
}
else
{
statusCode = Status.STATUS_INTERNAL_SERVER_ERROR;
}
String msg = ex.getMessage();
// remove log numbers. regEx => match 8 or more integers
msg = (msg != null) ? msg.replaceAll("\\d{8,}", "").trim() : "cmm.rest_api.model.import_failure";
throw new WebScriptException(statusCode, msg);
}
return model;
}
protected String getExtensionModule(InputStream inputStream, String fileName)
{
Element rootElement = null;
try
{
final DocumentBuilder db = XMLUtil.getDocumentBuilder();
rootElement = db.parse(inputStream).getDocumentElement();
}
catch (IOException io)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR, "cmm.rest_api.model.import_process_ext_module_file_failure", io);
}
catch (SAXException ex)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "cmm.rest_api.model.import_invalid_ext_module_entry", new Object[] { fileName }, ex);
}
if (rootElement != null && SHARE_EXT_MODULE_ROOT_ELEMENT.equals(rootElement.getNodeName()))
{
StringWriter sw = new StringWriter();
XMLUtil.print(rootElement, sw, false);
return sw.toString();
}
return null;
}
/**
* Simple POJO for model import result.
*
* @author Jamal Kaabi-Mofrad
*/
public static class ImportResult
{
private String importedModelName;
private String shareExtXMLFragment;
public ImportResult(CustomModel customModel, String shareExtXMLFragment)
{
this.shareExtXMLFragment = shareExtXMLFragment;
if (customModel != null)
{
this.importedModelName = customModel.getName();
}
}
public String getImportedModelName()
{
return this.importedModelName;
}
public String getShareExtXMLFragment()
{
return this.shareExtXMLFragment;
}
}
}

View File

@@ -0,0 +1,220 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api;
import org.alfresco.repo.dictionary.M2Model;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.api.model.CustomModelConstraint;
import org.alfresco.rest.api.model.CustomModelDownload;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
/**
* @author Jamal Kaabi-Mofrad
*/
public interface CustomModels
{
/**
* Gets the {@code org.alfresco.rest.api.model.CustomModel} representation for the given model
*
* @param modelName the model name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomModel} object
*/
public CustomModel getCustomModel(String modelName, Parameters parameters);
/**
* Gets a paged list of all custom models
*
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return a paged list of {@code org.alfresco.rest.api.model.CustomModel} objects
*/
public CollectionWithPagingInfo<CustomModel> getCustomModels(Parameters parameters);
/**
* Creates custom model
*
* @param model the custom model to create
* @return {@code org.alfresco.rest.api.model.CustomModel} object
*/
public CustomModel createCustomModel(CustomModel model);
/**
* Creates custom model from the imported {@link M2Model}.
*
* @param m2Model the model
* @return {@code org.alfresco.rest.api.model.CustomModel} object
*/
public CustomModel createCustomModel(M2Model m2Model);
/**
* Updates or activates/deactivates the custom model
*
* @param modelName the model name
* @param model the custom model to update (JSON payload)
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomModel} object
*/
public CustomModel updateCustomModel(String modelName, CustomModel model, Parameters parameters);
/**
* Deletes the custom model
*
* @param modelName the model name
*/
public void deleteCustomModel(String modelName);
/**
* Gets the {@code org.alfresco.rest.api.model.CustomType} representation of
* the given model's type
*
* @param modelName the model name
* @param typeName the model's type name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomType} object
*/
public CustomType getCustomType(String modelName, String typeName, Parameters parameters);
/**
* Gets a paged list of all the given custom model's types
*
* @param modelName the model name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return a paged list of {@code org.alfresco.rest.api.model.CustomType} objects
*/
public CollectionWithPagingInfo<CustomType> getCustomTypes(String modelName, Parameters parameters);
/**
* Creates custom model's type
*
* @param modelName the model name
* @param type the custom type to create within the given model
* @return {@code org.alfresco.rest.api.model.CustomType} object
*/
public CustomType createCustomType(String modelName, CustomType type);
/**
* Updates the custom model's type
*
* @param modelName the model name
* @param type the custom model's type to update (JSON payload)
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomType} object
*/
public CustomType updateCustomType(String modelName, CustomType type, Parameters parameters);
/**
* Deletes the custom model's type
*
* @param modelName the model name
* @param typeName the model's type name
*/
public void deleteCustomType(String modelName, String typeName);
/**
* Gets the {@code org.alfresco.rest.api.model.CustomAspect} representation of
* the given model's aspect
*
* @param modelName the model name
* @param aspectName the model's aspect name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomAspect} object
*/
public CustomAspect getCustomAspect(String modelName, String aspectName, Parameters parameters);
/**
* Gets a paged list of all the given custom model's aspects
*
* @param modelName the model name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return a paged list of {@code org.alfresco.rest.api.model.CustomAspect} objects
*/
public CollectionWithPagingInfo<CustomAspect> getCustomAspects(String modelName, Parameters parameters);
/**
* Creates custom model's aspect
*
* @param modelName the model name
* @param aspect the custom aspect to create within the given model
* @return {@code org.alfresco.rest.api.model.CustomAspect} object
*/
public CustomAspect createCustomAspect(String modelName, CustomAspect aspect);
/**
* Updates the custom model's aspect
*
* @param modelName the model name
* @param aspect the custom model's aspect to update (JSON payload)
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomAspect} object
*/
public CustomAspect updateCustomAspect(String modelName, CustomAspect aspect, Parameters parameters);
/**
* Deletes the custom model's aspect
*
* @param modelName the model name
* @param aspectName the model's aspect name
*/
public void deleteCustomAspect(String modelName, String aspectName);
/**
* Gets the {@code org.alfresco.rest.api.model.CustomModelConstraint}
* representation of the given model's constraint
*
* @param modelName the model name
* @param constraintName the model's constraint name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return {@code org.alfresco.rest.api.model.CustomModelConstraint} object
*/
public CustomModelConstraint getCustomModelConstraint(String modelName, String constraintName, Parameters parameters);
/**
* Gets a paged list of all of the given custom model's constraints
*
* @param modelName the model name
* @param parameters the {@link Parameters} object to get the parameters passed into the request
* @return a paged list of {@code org.alfresco.rest.api.model.CustomModelConstraint} objects
*/
public CollectionWithPagingInfo<CustomModelConstraint> getCustomModelConstraints(String modelName, Parameters parameters);
/**
* Creates custom model's constraint
*
* @param modelName the model name
* @param constraint the custom constraint to create within the given model
* @return {@code org.alfresco.rest.api.model.CustomModelConstraint} object
*/
public CustomModelConstraint createCustomModelConstraint(String modelName, CustomModelConstraint constraint);
/**
* Starts the creation of a downloadable archive file containing the
* custom model file and its associated Share extension module file (if requested).
*
* @param modelName the model name
* @param parameters the {@link Parameters} object to get the parameters
* passed into the request
* @return {@code org.alfresco.rest.api.model.CustomModelDownload} object
* containing the archive node reference
*/
public CustomModelDownload createDownload(String modelName, Parameters parameters);
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.cmm;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.rest.api.CustomModels;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Jamal Kaabi-Mofrad
*/
@RelationshipResource(name = "aspects", entityResource = CustomModelEntityResource.class, title = "Custom Model Aspects")
public class CustomModelAspectsRelation implements RelationshipResourceAction.Read<CustomAspect>,
RelationshipResourceAction.ReadById<CustomAspect>,
RelationshipResourceAction.Create<CustomAspect>,
RelationshipResourceAction.Update<CustomAspect>,
RelationshipResourceAction.Delete,
InitializingBean
{
private CustomModels customModels;
public void setCustomModels(CustomModels customModels)
{
this.customModels = customModels;
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "customModels", customModels);
}
@Override
@WebApiDescription(title = "Returns a paged list of all the custom model's aspects.")
public CollectionWithPagingInfo<CustomAspect> readAll(String modelName, Parameters parameters)
{
return customModels.getCustomAspects(modelName, parameters);
}
@Override
@WebApiDescription(title = "Returns custom aspect information for the given 'aspectName' in 'modelName'.")
public CustomAspect readById(String modelName, String aspectName, Parameters parameters)
{
return customModels.getCustomAspect(modelName, aspectName, parameters);
}
@Override
@WebApiDescription(title = "Removes the custom aspect for the given 'aspectName' in 'modelName'.")
public void delete(String modelName, String aspectName, Parameters parameters)
{
customModels.deleteCustomAspect(modelName, aspectName);
}
@Override
@WebApiDescription(title = "Updates the custom aspect in the given 'modelName'.")
public CustomAspect update(String modelName, CustomAspect aspect, Parameters parameters)
{
return customModels.updateCustomAspect(modelName, aspect, parameters);
}
@Override
@WebApiDescription(title = "Creates custom aspects for the model 'modelName'.")
public List<CustomAspect> create(String modelName, List<CustomAspect> aspects, Parameters parameters)
{
List<CustomAspect> result = new ArrayList<>(aspects.size());
for (CustomAspect aspect : aspects)
{
result.add(customModels.createCustomAspect(modelName, aspect));
}
return result;
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.cmm;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.rest.api.CustomModels;
import org.alfresco.rest.api.model.CustomModelConstraint;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Jamal Kaabi-Mofrad
*/
@RelationshipResource(name = "constraints", entityResource = CustomModelEntityResource.class, title = "Custom Model Constraints")
public class CustomModelConstraintRelation implements RelationshipResourceAction.Read<CustomModelConstraint>,
RelationshipResourceAction.ReadById<CustomModelConstraint>,
RelationshipResourceAction.Create<CustomModelConstraint>,
InitializingBean
{
private CustomModels customModels;
public void setCustomModels(CustomModels customModels)
{
this.customModels = customModels;
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "customModels", customModels);
}
@Override
@WebApiDescription(title = "Returns a paged list of all the custom model's constraints.")
public CollectionWithPagingInfo<CustomModelConstraint> readAll(String modelName, Parameters parameters)
{
return customModels.getCustomModelConstraints(modelName, parameters);
}
@Override
@WebApiDescription(title = "Returns custom constraint information for the given 'constraintName' in 'modelName'.")
public CustomModelConstraint readById(String modelName, String constraintName, Parameters parameters)
{
return customModels.getCustomModelConstraint(modelName, constraintName, parameters);
}
@Override
@WebApiDescription(title = "Creates custom constraints for the model 'modelName'.")
public List<CustomModelConstraint> create(String modelName, List<CustomModelConstraint> constraints, Parameters parameters)
{
List<CustomModelConstraint> result = new ArrayList<>(constraints.size());
for (CustomModelConstraint constraint : constraints)
{
result.add(customModels.createCustomModelConstraint(modelName, constraint));
}
return result;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.cmm;
import java.util.Collections;
import java.util.List;
import org.alfresco.rest.api.CustomModels;
import org.alfresco.rest.api.model.CustomModelDownload;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Jamal Kaabi-Mofrad
*/
@RelationshipResource(name = "download", entityResource = CustomModelEntityResource.class, title = "Custom Model Download")
public class CustomModelDownloadRelation implements RelationshipResourceAction.Create<CustomModelDownload>, InitializingBean
{
private CustomModels customModels;
public void setCustomModels(CustomModels customModels)
{
this.customModels = customModels;
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "customModels", customModels);
}
@Override
@WebApiDescription(title = "Creates download node containing the custom model file and if specified, its associated Share extension module file.")
public List<CustomModelDownload> create(String modelName, List<CustomModelDownload> download, Parameters parameters)
{
CustomModelDownload result = customModels.createDownload(modelName, parameters);
return Collections.singletonList(result);
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.cmm;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.rest.api.CustomModels;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Jamal Kaabi-Mofrad
*/
@EntityResource(name = "cmm", title = "Custom Model Management")
public class CustomModelEntityResource implements EntityResourceAction.Read<CustomModel>,
EntityResourceAction.ReadById<CustomModel>,
EntityResourceAction.Create<CustomModel>,
EntityResourceAction.Update<CustomModel>,
EntityResourceAction.Delete,
InitializingBean
{
private CustomModels customModels;
public void setCustomModels(CustomModels customModels)
{
this.customModels = customModels;
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "customModels", customModels);
}
@Override
@WebApiDescription(title="Returns custom model information for the given model name.")
public CustomModel readById(String modelName, Parameters parameters) throws EntityNotFoundException
{
return customModels.getCustomModel(modelName, parameters);
}
@Override
@WebApiDescription(title="Returns a paged list of all custom models.")
public CollectionWithPagingInfo<CustomModel> readAll(Parameters parameters)
{
return customModels.getCustomModels(parameters);
}
@Override
@WebApiDescription(title="Creates custom model(s).")
public List<CustomModel> create(List<CustomModel> entity, Parameters parameters)
{
List<CustomModel> result = new ArrayList<>(entity.size());
for (CustomModel cm : entity)
{
result.add(customModels.createCustomModel(cm));
}
return result;
}
@Override
@WebApiDescription(title = "Updates or activates/deactivates the custom model.")
public CustomModel update(String modelName, CustomModel entity, Parameters parameters)
{
return customModels.updateCustomModel(modelName, entity, parameters);
}
@Override
@WebApiDescription(title = "Deletes the custom model.")
public void delete(String modelName, Parameters parameters)
{
customModels.deleteCustomModel(modelName);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.cmm;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.rest.api.CustomModels;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.resource.RelationshipResource;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.InitializingBean;
/**
* @author Jamal Kaabi-Mofrad
*/
@RelationshipResource(name = "types", entityResource = CustomModelEntityResource.class, title = "Custom Model Types")
public class CustomModelTypesRelation implements RelationshipResourceAction.Read<CustomType>,
RelationshipResourceAction.ReadById<CustomType>,
RelationshipResourceAction.Create<CustomType>,
RelationshipResourceAction.Update<CustomType>,
RelationshipResourceAction.Delete,
InitializingBean
{
private CustomModels customModels;
public void setCustomModels(CustomModels customModels)
{
this.customModels = customModels;
}
@Override
public void afterPropertiesSet() throws Exception
{
PropertyCheck.mandatory(this, "customModels", customModels);
}
@Override
@WebApiDescription(title = "Returns a paged list of all the custom model's types.")
public CollectionWithPagingInfo<CustomType> readAll(String modelName, Parameters parameters)
{
return customModels.getCustomTypes(modelName, parameters);
}
@Override
@WebApiDescription(title = "Returns custom type information for the given 'typeName' in 'modelName'.")
public CustomType readById(String modelName, String typeName, Parameters parameters)
{
return customModels.getCustomType(modelName, typeName, parameters);
}
@Override
@WebApiDescription(title = "Removes the custom type for the given 'typeName' in 'modelName'.")
public void delete(String modelName, String typeName, Parameters parameters)
{
customModels.deleteCustomType(modelName, typeName);
}
@Override
@WebApiDescription(title = "Updates the custom type in the given 'modelName'.")
public CustomType update(String modelName, CustomType type, Parameters parameters)
{
return customModels.updateCustomType(modelName, type, parameters);
}
@Override
@WebApiDescription(title = "Creates custom types for the model 'modelName'.")
public List<CustomType> create(String modelName, List<CustomType> types, Parameters parameters)
{
List<CustomType> result = new ArrayList<>(types.size());
for (CustomType type : types)
{
result.add(customModels.createCustomType(modelName, type));
}
return result;
}
}

View File

@@ -0,0 +1,4 @@
@WebApi(name="alfresco", scope=Api.SCOPE.PRIVATE, version=1)
package org.alfresco.rest.api.cmm;
import org.alfresco.rest.framework.Api;
import org.alfresco.rest.framework.WebApi;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.service.namespace.QName;
/**
* @author Jamal Kaabi-Mofrad
*/
public abstract class AbstractClassModel extends AbstractCommonDetails
{
/* package */String parentName;
/* package */List<CustomModelProperty> properties = Collections.emptyList();
public String getParentName()
{
return this.parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public List<CustomModelProperty> getProperties()
{
return this.properties;
}
public void setProperties(List<CustomModelProperty> properties)
{
this.properties = properties;
}
/* package */<T> List<T> setList(List<T> sourceList)
{
if (sourceList == null)
{
return Collections.<T> emptyList();
}
return new ArrayList<>(sourceList);
}
/* package */String getParentNameAsString(QName parentQName)
{
if (parentQName != null)
{
return parentQName.toPrefixString();
}
return null;
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
/**
* @author Jamal Kaabi-Mofrad
*/
public abstract class AbstractCommonDetails implements Comparable<AbstractCommonDetails>
{
/* package */String name;
/* package */String prefixedName;
/* package */String title;
/* package */String description;
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
public String getPrefixedName()
{
return this.prefixedName;
}
public String getTitle()
{
return this.title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return this.description;
}
public void setDescription(String description)
{
this.description = description;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof CustomModelConstraint))
{
return false;
}
CustomModelConstraint other = (CustomModelConstraint) obj;
if (this.name == null)
{
if (other.name != null)
{
return false;
}
}
else if (!this.name.equals(other.name))
{
return false;
}
return true;
}
@Override
public int compareTo(AbstractCommonDetails other)
{
return this.name.compareTo(other.getName());
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.List;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CustomAspect extends AbstractClassModel
{
public CustomAspect()
{
}
public CustomAspect(AspectDefinition aspectDefinition, MessageLookup messageLookup, List<CustomModelProperty> properties)
{
this.name = aspectDefinition.getName().getLocalName();
this.prefixedName = aspectDefinition.getName().toPrefixString();
this.title = aspectDefinition.getTitle(messageLookup);
this.description = aspectDefinition.getDescription(messageLookup);
this.parentName = getParentNameAsString(aspectDefinition.getParentName());
this.properties = setList(properties);
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(512);
builder.append("CustomAspect [name=").append(this.name)
.append(", prefixedName=").append(this.prefixedName)
.append(", title=").append(this.title)
.append(", description=").append(this.description)
.append(", parentName=").append(parentName)
.append(", properties=").append(properties)
.append(']');
return builder.toString();
}
}

View File

@@ -0,0 +1,217 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.List;
import org.alfresco.service.cmr.dictionary.CustomModelDefinition;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CustomModel implements Comparable<CustomModel>
{
public static enum ModelStatus
{
ACTIVE, DRAFT
}
private String name;
private String author;
private String description;
private ModelStatus status;
private String namespaceUri;
private String namespacePrefix;
private List<CustomType> types;
private List<CustomAspect> aspects;
private List<CustomModelConstraint> constraints;
public CustomModel()
{
}
public CustomModel(CustomModelDefinition modelDefinition)
{
this(modelDefinition, null, null, null);
}
public CustomModel(CustomModelDefinition modelDefinition, List<CustomType> types, List<CustomAspect> aspects, List<CustomModelConstraint> constraints)
{
this.name = modelDefinition.getName().getLocalName();
this.author = modelDefinition.getAuthor();
this.description = modelDefinition.getDescription();
this.status = modelDefinition.isActive() ? ModelStatus.ACTIVE : ModelStatus.DRAFT;
// we don't need to check for NoSuchElementException, as we don't allow
// the model to be saved without a valid namespace
NamespaceDefinition nsd = modelDefinition.getNamespaces().iterator().next();
this.namespaceUri = nsd.getUri();
this.namespacePrefix = nsd.getPrefix();
this.types = types;
this.aspects = aspects;
this.constraints = constraints;
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
public String getAuthor()
{
return this.author;
}
public void setAuthor(String author)
{
this.author = author;
}
public String getDescription()
{
return this.description;
}
public void setDescription(String description)
{
this.description = description;
}
public ModelStatus getStatus()
{
return this.status;
}
public void setStatus(ModelStatus status)
{
this.status = status;
}
public String getNamespaceUri()
{
return this.namespaceUri;
}
public void setNamespaceUri(String namespaceUri)
{
this.namespaceUri = namespaceUri;
}
public String getNamespacePrefix()
{
return this.namespacePrefix;
}
public void setNamespacePrefix(String namespacePrefix)
{
this.namespacePrefix = namespacePrefix;
}
public List<CustomType> getTypes()
{
return this.types;
}
public void setTypes(List<CustomType> types)
{
this.types = types;
}
public List<CustomAspect> getAspects()
{
return this.aspects;
}
public void setAspects(List<CustomAspect> aspects)
{
this.aspects = aspects;
}
public List<CustomModelConstraint> getConstraints()
{
return this.constraints;
}
public void setConstraints(List<CustomModelConstraint> constraints)
{
this.constraints = constraints;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof CustomModel))
{
return false;
}
CustomModel other = (CustomModel) obj;
if (this.name == null)
{
if (other.name != null)
{
return false;
}
}
else if (!this.name.equals(other.name))
{
return false;
}
return true;
}
@Override
public int compareTo(CustomModel customModel)
{
return this.name.compareTo(customModel.getName());
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(512);
builder.append("CustomModel [name=").append(this.name).append(", author=").append(this.author)
.append(", description=").append(this.description).append(", status=").append(this.status)
.append(", namespaceUri=").append(this.namespaceUri).append(", namespacePrefix=")
.append(this.namespacePrefix).append(']');
return builder.toString();
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelConstraint extends AbstractCommonDetails
{
private String type;
private List<CustomModelNamedValue> parameters = Collections.emptyList();
public CustomModelConstraint()
{
}
public CustomModelConstraint(ConstraintDefinition constraintDefinition, MessageLookup messageLookup)
{
this.name = constraintDefinition.getName().getLocalName();
this.prefixedName = constraintDefinition.getConstraint().getShortName();
this.type = constraintDefinition.getConstraint().getType();
this.title = constraintDefinition.getTitle(messageLookup);
this.description = constraintDefinition.getDescription(messageLookup);
this.parameters = convertToNamedValue(constraintDefinition.getConstraint().getParameters());
}
private List<CustomModelNamedValue> convertToNamedValue(Map<String, Object> params)
{
List<CustomModelNamedValue> list = new ArrayList<>(params.size());
for (Entry<String, Object> en : params.entrySet())
{
list.add(new CustomModelNamedValue(en.getKey(), en.getValue()));
}
return list;
}
public String getType()
{
return this.type;
}
public void setType(String type)
{
this.type = type;
}
public List<CustomModelNamedValue> getParameters()
{
return this.parameters;
}
public void setParameters(List<CustomModelNamedValue> parameters)
{
this.parameters = parameters;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(300);
builder.append("CustomModelConstraint [name=").append(this.name)
.append(", prefixedName=").append(this.prefixedName)
.append(", type=").append(this.type)
.append(", title=").append(this.title)
.append(", description=").append(this.description)
.append(", parameters=").append(this.parameters)
.append(']');
return builder.toString();
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelDownload implements Comparable<CustomModelDownload>
{
private String nodeRef;
public CustomModelDownload()
{
}
public CustomModelDownload(NodeRef nodeRef)
{
this.nodeRef = nodeRef.toString();
}
public String getNodeRef()
{
return this.nodeRef;
}
public void setNodeRef(String nodeRef)
{
this.nodeRef = nodeRef;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((this.nodeRef == null) ? 0 : this.nodeRef.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof CustomModelDownload))
{
return false;
}
CustomModelDownload other = (CustomModelDownload) obj;
if (this.nodeRef == null)
{
if (other.nodeRef != null)
{
return false;
}
}
else if (!this.nodeRef.equals(other.nodeRef))
{
return false;
}
return true;
}
@Override
public int compareTo(CustomModelDownload other)
{
return this.nodeRef.toString().compareTo(other.getNodeRef().toString());
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.rest.framework.core.exceptions.InvalidArgumentException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
/**
*
*
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelNamedValue implements Comparable<CustomModelNamedValue>
{
private String name;
private String simpleValue = null;
private List<String> listValue = null;
public CustomModelNamedValue()
{
}
public CustomModelNamedValue(String name, Object value)
{
this.name = name;
if (value instanceof List<?>)
{
List<?> values = (List<?>) value;
listValue = new ArrayList<>(values.size());
for(Object val : values)
{
listValue.add(convertToString(val));
}
}
else
{
simpleValue = convertToString(value);
}
}
private String convertToString(Object value)
{
try
{
return DefaultTypeConverter.INSTANCE.convert(String.class, value);
}
catch (TypeConversionException e)
{
throw new InvalidArgumentException("Cannot convert to string '" + value + "'.");
}
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
public String getSimpleValue()
{
return this.simpleValue;
}
public void setSimpleValue(String simpleValue)
{
this.simpleValue = simpleValue;
}
public List<String> getListValue()
{
return this.listValue;
}
public void setListValue(List<String> listValue)
{
this.listValue = listValue;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof CustomModelNamedValue))
{
return false;
}
CustomModelNamedValue other = (CustomModelNamedValue) obj;
if (this.name == null)
{
if (other.name != null)
{
return false;
}
}
else if (!this.name.equals(other.name))
{
return false;
}
return true;
}
@Override
public int compareTo(CustomModelNamedValue other)
{
return name.compareTo(other.getName());
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(120);
builder.append("CustomModelNamedValue [name=").append(this.name)
.append(", simpleValue=").append(this.simpleValue)
.append(", listValue=").append(this.listValue)
.append(']');
return builder.toString();
}
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.dictionary.Facetable;
import org.alfresco.repo.dictionary.IndexTokenisationMode;
import org.alfresco.service.cmr.dictionary.ConstraintDefinition;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelProperty extends AbstractCommonDetails
{
private String dataType;
private boolean isMandatory;
private boolean isMandatoryEnforced;
private boolean isMultiValued;
private String defaultValue;
private boolean isIndexed = true;
private Facetable facetable = Facetable.UNSET;
private IndexTokenisationMode indexTokenisationMode;
private List<String> constraintRefs = Collections.emptyList();
private List<CustomModelConstraint> constraints = Collections.emptyList();
public CustomModelProperty()
{
}
public CustomModelProperty(PropertyDefinition propertyDefinition, MessageLookup messageLookup)
{
this.name = propertyDefinition.getName().getLocalName();
this.prefixedName = propertyDefinition.getName().toPrefixString();
this.title = propertyDefinition.getTitle(messageLookup);
this.dataType = propertyDefinition.getDataType().getName().toPrefixString();
this.description = propertyDefinition.getDescription(messageLookup);
this.isMandatory = propertyDefinition.isMandatory();
this.isMandatoryEnforced = propertyDefinition.isMandatoryEnforced();
this.isMultiValued = propertyDefinition.isMultiValued();
this.defaultValue = propertyDefinition.getDefaultValue();
this.isIndexed = propertyDefinition.isIndexed();
this.facetable = propertyDefinition.getFacetable();
this.indexTokenisationMode = propertyDefinition.getIndexTokenisationMode();
List<ConstraintDefinition> constraintDefs = propertyDefinition.getConstraints();
if (constraintDefs.size() > 0)
{
this.constraintRefs = new ArrayList<>();
this.constraints = new ArrayList<>();
for (ConstraintDefinition cd : constraintDefs)
{
if (cd.getRef() != null)
{
constraintRefs.add(cd.getRef().toPrefixString());
}
else
{
constraints.add(new CustomModelConstraint(cd, messageLookup));
}
}
}
}
public String getDataType()
{
return this.dataType;
}
public void setDataType(String dataType)
{
this.dataType = dataType;
}
public boolean isMandatory()
{
return this.isMandatory;
}
public void setMandatory(boolean isMandatory)
{
this.isMandatory = isMandatory;
}
public boolean isMandatoryEnforced()
{
return this.isMandatoryEnforced;
}
public void setMandatoryEnforced(boolean isMandatoryEnforced)
{
this.isMandatoryEnforced = isMandatoryEnforced;
}
public boolean isMultiValued()
{
return this.isMultiValued;
}
public void setMultiValued(boolean isMultiValued)
{
this.isMultiValued = isMultiValued;
}
public String getDefaultValue()
{
return this.defaultValue;
}
public void setDefaultValue(String defaultValue)
{
this.defaultValue = defaultValue;
}
public boolean isIndexed()
{
return this.isIndexed;
}
public void setIndexed(boolean isIndexed)
{
this.isIndexed = isIndexed;
}
public Facetable getFacetable()
{
return this.facetable;
}
public void setFacetable(Facetable facetable)
{
this.facetable = facetable;
}
public IndexTokenisationMode getIndexTokenisationMode()
{
return this.indexTokenisationMode;
}
public void setIndexTokenisationMode(IndexTokenisationMode indexTokenisationMode)
{
this.indexTokenisationMode = indexTokenisationMode;
}
public List<String> getConstraintRefs()
{
return this.constraintRefs;
}
public void setConstraintRefs(List<String> constraintRefs)
{
this.constraintRefs = constraintRefs;
}
public List<CustomModelConstraint> getConstraints()
{
return this.constraints;
}
public void setConstraints(List<CustomModelConstraint> constraints)
{
this.constraints = constraints;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(612);
builder.append("CustomModelProperty [name=").append(this.name)
.append(", prefixedName=").append(this.prefixedName)
.append(", title=").append(this.title)
.append(", description=").append(this.description)
.append(", dataType=").append(this.dataType)
.append(", isMandatory=").append(this.isMandatory)
.append(", isMandatoryEnforced=").append(this.isMandatoryEnforced)
.append(", isMultiValued=").append(this.isMultiValued)
.append(", defaultValue=").append(this.defaultValue)
.append(", isIndexed=").append(this.isIndexed)
.append(", facetable=").append(this.facetable)
.append(", indexTokenisationMode=").append(this.indexTokenisationMode)
.append(", constraintRefs=").append(this.constraintRefs)
.append(", constraints=").append(this.constraints)
.append(']');
return builder.toString();
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.model;
import java.util.List;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
import org.alfresco.service.cmr.i18n.MessageLookup;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CustomType extends AbstractClassModel
{
public CustomType()
{
}
public CustomType(TypeDefinition typeDefinition, MessageLookup messageLookup, List<CustomModelProperty> properties)
{
this.name = typeDefinition.getName().getLocalName();
this.prefixedName = typeDefinition.getName().toPrefixString();
this.title = typeDefinition.getTitle(messageLookup);
this.description = typeDefinition.getDescription(messageLookup);
this.parentName = getParentNameAsString(typeDefinition.getParentName());
this.properties = setList(properties);
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder(512);
builder.append("CustomType [name=").append(this.name)
.append(", prefixedName=").append(this.prefixedName)
.append(", title=").append(this.title)
.append(", description=").append(this.description)
.append(", parentName=").append(parentName)
.append(", properties=").append(properties)
.append(']');
return builder.toString();
}
}

View File

@@ -93,4 +93,9 @@ public class RemoteApi01TestSuite extends TestSuite
suite.addTest(new JUnit4TestAdapter(org.alfresco.rest.workflow.api.tests.ProcessWorkflowApiTest.class)); suite.addTest(new JUnit4TestAdapter(org.alfresco.rest.workflow.api.tests.ProcessWorkflowApiTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.rest.workflow.api.tests.TaskWorkflowApiTest.class)); suite.addTest(new JUnit4TestAdapter(org.alfresco.rest.workflow.api.tests.TaskWorkflowApiTest.class));
} }
static void tests8(TestSuite suite) //
{
suite.addTest(org.alfresco.rest.api.tests.CMMApiTestSuite.suite());
}
} }

View File

@@ -28,6 +28,7 @@ import org.alfresco.repo.web.scripts.admin.AdminWebScriptTest;
import org.alfresco.repo.web.scripts.audit.AuditWebScriptTest; import org.alfresco.repo.web.scripts.audit.AuditWebScriptTest;
import org.alfresco.repo.web.scripts.blogs.BlogServiceTest; import org.alfresco.repo.web.scripts.blogs.BlogServiceTest;
import org.alfresco.repo.web.scripts.comment.CommentsApiTest; import org.alfresco.repo.web.scripts.comment.CommentsApiTest;
import org.alfresco.repo.web.scripts.custommodel.CustomModelImportTest;
import org.alfresco.repo.web.scripts.dictionary.DictionaryRestApiTest; import org.alfresco.repo.web.scripts.dictionary.DictionaryRestApiTest;
import org.alfresco.repo.web.scripts.discussion.DiscussionRestApiTest; import org.alfresco.repo.web.scripts.discussion.DiscussionRestApiTest;
import org.alfresco.repo.web.scripts.facet.FacetRestApiTest; import org.alfresco.repo.web.scripts.facet.FacetRestApiTest;
@@ -98,12 +99,13 @@ public class WebScriptTestSuite extends TestSuite
suite.addTestSuite( SOLRWebScriptTest.class ); suite.addTestSuite( SOLRWebScriptTest.class );
suite.addTestSuite( SubscriptionServiceRestApiTest.class ); suite.addTestSuite( SubscriptionServiceRestApiTest.class );
suite.addTestSuite( FacetRestApiTest.class ); suite.addTestSuite( FacetRestApiTest.class );
suite.addTestSuite( CommentsApiTest.class ); suite.addTestSuite( CommentsApiTest.class );
suite.addTestSuite( DeclarativeSpreadsheetWebScriptTest.class ); suite.addTestSuite( DeclarativeSpreadsheetWebScriptTest.class );
suite.addTestSuite( XssVulnerabilityTest.class ); suite.addTestSuite( XssVulnerabilityTest.class );
suite.addTestSuite( LinksRestApiTest.class ); suite.addTestSuite( LinksRestApiTest.class );
suite.addTestSuite( RemoteFileFolderLoaderTest.class ); suite.addTestSuite( RemoteFileFolderLoaderTest.class );
suite.addTestSuite( ReadOnlyTransactionInGetRestApiTest.class ); suite.addTestSuite( ReadOnlyTransactionInGetRestApiTest.class );
suite.addTestSuite( CustomModelImportTest.class );
// This uses a slightly different context // This uses a slightly different context
// As such, we can't run it in the same suite as the others, // As such, we can't run it in the same suite as the others,
// due to finalisers closing caches when we're not looking // due to finalisers closing caches when we're not looking

View File

@@ -0,0 +1,487 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.web.scripts.custommodel;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.dictionary.CustomModelServiceImpl;
import org.alfresco.repo.dictionary.M2Association;
import org.alfresco.repo.dictionary.M2Model;
import org.alfresco.repo.dictionary.M2Type;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.web.scripts.BaseWebScriptTest;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.PropertyMap;
import org.alfresco.util.TempFileProvider;
import org.alfresco.util.XMLUtil;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.extensions.webscripts.TestWebScriptServer.PostRequest;
import org.springframework.extensions.webscripts.TestWebScriptServer.Response;
import org.springframework.util.ResourceUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
/**
* This class tests the custom model upload REST API.
*
* @author Jamal Kaabi-Mofrad
*/
public class CustomModelImportTest extends BaseWebScriptTest
{
private static final String NON_ADMIN_USER = "nonAdminUserName";
private static final String CUSTOM_MODEL_ADMIN = "customModelAdmin";
private static final String RESOURCE_PREFIX = "custommodel/";
private static final String UPLOAD_URL = "/api/cmm/upload";
private static final int BUFFER_SIZE = 20 * 1024;
private MutableAuthenticationService authenticationService;
private AuthorityService authorityService;
private PersonService personService;
private RetryingTransactionHelper transactionHelper;
private CustomModelService customModelService;
private List<String> importedModels = new ArrayList<>();
private List<File> tempFiles = new ArrayList<>();
@Override
protected void setUp() throws Exception
{
super.setUp();
authenticationService = getServer().getApplicationContext().getBean("AuthenticationService", MutableAuthenticationService.class);
authorityService = getServer().getApplicationContext().getBean("AuthorityService", AuthorityService.class);
personService = getServer().getApplicationContext().getBean("PersonService", PersonService.class);
transactionHelper = getServer().getApplicationContext().getBean("retryingTransactionHelper", RetryingTransactionHelper.class);
customModelService = getServer().getApplicationContext().getBean("customModelService", CustomModelService.class);
AuthenticationUtil.clearCurrentSecurityContext();
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
createUser(NON_ADMIN_USER);
createUser(CUSTOM_MODEL_ADMIN);
if (!authorityService.getContainingAuthorities(AuthorityType.GROUP, CUSTOM_MODEL_ADMIN, true).contains(
CustomModelServiceImpl.GROUP_ALFRESCO_MODEL_ADMINISTRATORS_AUTHORITY))
{
authorityService.addAuthority(CustomModelServiceImpl.GROUP_ALFRESCO_MODEL_ADMINISTRATORS_AUTHORITY, CUSTOM_MODEL_ADMIN);
}
return null;
}
});
AuthenticationUtil.setFullyAuthenticatedUser(CUSTOM_MODEL_ADMIN);
}
@Override
public void tearDown() throws Exception
{
for (File file : tempFiles)
{
file.delete();
}
transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
for (String modelName : importedModels)
{
customModelService.deleteCustomModel(modelName);
}
return null;
}
});
AuthenticationUtil.runAsSystem(new RunAsWork<Void>()
{
@Override
public Void doWork() throws Exception
{
transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
public Void execute() throws Throwable
{
deleteUser(NON_ADMIN_USER);
deleteUser(CUSTOM_MODEL_ADMIN);
return null;
}
});
return null;
}
});
AuthenticationUtil.clearCurrentSecurityContext();
super.tearDown();
}
public void testValidUpload_ModelAndExtModule() throws Exception
{
File zipFile = getResourceFile("validModelAndExtModule.zip");
PostRequest postRequest = buildMultipartPostRequest(zipFile);
AuthenticationUtil.setFullyAuthenticatedUser(NON_ADMIN_USER);
Response response = sendRequest(postRequest, 403);
AuthenticationUtil.setFullyAuthenticatedUser(CUSTOM_MODEL_ADMIN);
response = sendRequest(postRequest, 200);
JSONObject json = new JSONObject(new JSONTokener(response.getContentAsString()));
String importedModelName = json.getString("modelName");
importedModels.add(importedModelName);
String extModule = json.getString("shareExtModule");
Document document = XMLUtil.parse(extModule);
NodeList nodes = document.getElementsByTagName("id");
assertEquals(1, nodes.getLength());
assertNotNull(nodes.item(0).getTextContent());
}
public void testValidUpload_ModelOnly() throws Exception
{
File zipFile = getResourceFile("validModel.zip");
PostRequest postRequest = buildMultipartPostRequest(zipFile);
AuthenticationUtil.setFullyAuthenticatedUser(NON_ADMIN_USER);
Response response = sendRequest(postRequest, 403);
AuthenticationUtil.setFullyAuthenticatedUser(CUSTOM_MODEL_ADMIN);
response = sendRequest(postRequest, 200);
JSONObject json = new JSONObject(new JSONTokener(response.getContentAsString()));
String importedModelName = json.getString("modelName");
importedModels.add(importedModelName);
assertFalse(json.has("shareExtModule"));
// Import the same model again
sendRequest(postRequest, 409); // name conflict
}
public void testValidUpload_ExtModuleOnly() throws Exception
{
File zipFile = getResourceFile("validExtModule.zip");
PostRequest postRequest = buildMultipartPostRequest(zipFile);
AuthenticationUtil.setFullyAuthenticatedUser(NON_ADMIN_USER);
Response response = sendRequest(postRequest, 403);
AuthenticationUtil.setFullyAuthenticatedUser(CUSTOM_MODEL_ADMIN);
response = sendRequest(postRequest, 200);
JSONObject json = new JSONObject(new JSONTokener(response.getContentAsString()));
assertFalse(json.has("modelName"));
String extModule = json.getString("shareExtModule");
Document document = XMLUtil.parse(extModule);
NodeList nodes = document.getElementsByTagName("id");
assertEquals(1, nodes.getLength());
assertNotNull(nodes.item(0).getTextContent());
}
public void testNotZipFileUpload() throws Exception
{
File file = getResourceFile("validModel.zip");
ZipFile zipFile = new ZipFile(file);
ZipEntry zipEntry = zipFile.entries().nextElement();
File unzippedModelFile = TempFileProvider.createTempFile(zipFile.getInputStream(zipEntry), "validModel", ".xml");
tempFiles.add(unzippedModelFile);
zipFile.close();
PostRequest postRequest = buildMultipartPostRequest(unzippedModelFile);
sendRequest(postRequest, 400); // CMM upload supports only zip file.
}
public void testInvalidZipUpload() throws Exception
{
String content = "<note>"
+ "<from>Jane</from>"
+ "<to>John</to>"
+ "<heading>Upload test</heading>"
+ "<body>This is an invalid model or a Share extension module</body>"
+"</note>";
ZipEntryContext context = new ZipEntryContext("invalidFormat.xml", content.getBytes());
File zipFile = createZip(context);
PostRequest postRequest = buildMultipartPostRequest(zipFile);
sendRequest(postRequest, 400); // Invalid. Neither a model nor a Share extension module file
}
public void testUploadModel_Invalid() throws Exception
{
long timestamp = System.currentTimeMillis();
final String modelName = getClass().getSimpleName() + timestamp;
final String prefix = "prefix" + timestamp;
final String uri = "uriNamespace" + timestamp;
M2Model model = M2Model.createModel(prefix + QName.NAMESPACE_PREFIX + modelName);
model.setAuthor("Admin");
model.setDescription("Desc");
ByteArrayOutputStream xml = new ByteArrayOutputStream();
model.toXML(xml);
ZipEntryContext context = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
File zipFile = createZip(context);
PostRequest postRequest = buildMultipartPostRequest(zipFile);
sendRequest(postRequest, 409); // no namespace has been defined
// Create two namespaces
model.createNamespace(uri, prefix);
model.createNamespace(uri + "anotherUri", prefix + "anotherPrefix");
xml = new ByteArrayOutputStream();
model.toXML(xml);
context = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
zipFile = createZip(context);
postRequest = buildMultipartPostRequest(zipFile);
sendRequest(postRequest, 409); // custom model can only have one namespace
}
public void testUploadModel_UnsupportedModelElements() throws Exception
{
// Note: here we only test a couple of not-supported model elements to check for the correct status code.
// This test should be removed when we implement the required support
long timestamp = System.currentTimeMillis();
final String modelName = getClass().getSimpleName() + timestamp;
final String prefix = "prefix"+timestamp;
final String uri = "uriNamespace"+timestamp;
final String aspectName = prefix + QName.NAMESPACE_PREFIX + "testAspec";
final String typeName = prefix + QName.NAMESPACE_PREFIX + "testType";
final String associationName = prefix + QName.NAMESPACE_PREFIX + "testAssociation";
M2Model model = M2Model.createModel(prefix + QName.NAMESPACE_PREFIX + modelName);
model.createNamespace(uri, prefix);
model.setAuthor("John Doe");
model.createAspect(aspectName);
model.createImport(NamespaceService.CONTENT_MODEL_1_0_URI, NamespaceService.CONTENT_MODEL_PREFIX);
M2Type type = model.createType(typeName);
// Add 'association' not supported yet.
M2Association association = type.createAssociation(associationName);
association.setSourceMandatory(false);
association.setSourceMany(false);
association.setTargetMandatory(false);
association.setTargetClassName("cm:content");
ByteArrayOutputStream xml = new ByteArrayOutputStream();
model.toXML(xml);
ZipEntryContext context = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
File zipFile = createZip(context);
PostRequest postRequest = buildMultipartPostRequest(zipFile);
sendRequest(postRequest, 409); // <associations> element is not supported yet
type.removeAssociation(associationName);
// Add 'mandatory-aspect' not supported yet.
type.addMandatoryAspect(aspectName);
xml = new ByteArrayOutputStream();
model.toXML(xml);
context = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
zipFile = createZip(context);
postRequest = buildMultipartPostRequest(zipFile);
sendRequest(postRequest, 409); // <mandatory-aspects> element is not supported yet
}
public void testInvalidNumberOfZipEntries() throws Exception
{
long timestamp = System.currentTimeMillis();
String modelName = getClass().getSimpleName() + timestamp;
String prefix = "prefix" + timestamp;
String uri = "uriNamespace" + timestamp;
// Model one
M2Model modelOne = M2Model.createModel(prefix + QName.NAMESPACE_PREFIX + modelName);
modelOne.createNamespace(uri, prefix);
modelOne.setDescription("Model 1");
ByteArrayOutputStream xml = new ByteArrayOutputStream();
modelOne.toXML(xml);
ZipEntryContext contextOne = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
// Model two
modelName += "two";
prefix += "two";
uri += "two";
M2Model modelTwo = M2Model.createModel(prefix + QName.NAMESPACE_PREFIX + modelName);
modelTwo.createNamespace(uri, prefix);
modelTwo.setDescription("Model 2");
xml = new ByteArrayOutputStream();
modelTwo.toXML(xml);
ZipEntryContext contextTwo = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
// Model three
modelName += "three";
prefix += "three";
uri += "three";
M2Model modelThree = M2Model.createModel(prefix + QName.NAMESPACE_PREFIX + modelName);
modelThree.createNamespace(uri, prefix);
modelThree.setDescription("Model 3");
xml = new ByteArrayOutputStream();
modelThree.toXML(xml);
ZipEntryContext contextThree = new ZipEntryContext(modelName + ".xml", xml.toByteArray());
File zipFile = createZip(contextOne, contextTwo, contextThree);
PostRequest postRequest = buildMultipartPostRequest(zipFile);
sendRequest(postRequest, 400); // more than two zip entries
}
public PostRequest buildMultipartPostRequest(File file) throws IOException
{
Part[] parts = { new FilePart("filedata", file.getName(), file, "application/zip", null) };
MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, new HttpMethodParams());
ByteArrayOutputStream os = new ByteArrayOutputStream();
multipartRequestEntity.writeRequest(os);
PostRequest postReq = new PostRequest(UPLOAD_URL, os.toByteArray(), multipartRequestEntity.getContentType());
return postReq;
}
private void createUser(String userName)
{
if (!authenticationService.authenticationExists(userName))
{
authenticationService.createAuthentication(userName, "PWD".toCharArray());
}
if (!personService.personExists(userName))
{
PropertyMap ppOne = new PropertyMap(4);
ppOne.put(ContentModel.PROP_USERNAME, userName);
ppOne.put(ContentModel.PROP_FIRSTNAME, "firstName");
ppOne.put(ContentModel.PROP_LASTNAME, "lastName");
ppOne.put(ContentModel.PROP_EMAIL, "email@email.com");
ppOne.put(ContentModel.PROP_JOBTITLE, "jobTitle");
personService.createPerson(ppOne);
}
}
private void deleteUser(String userName)
{
if (personService.personExists(userName))
{
personService.deletePerson(userName);
}
}
private File getResourceFile(String xmlFileName) throws FileNotFoundException
{
URL url = CustomModelImportTest.class.getClassLoader().getResource(RESOURCE_PREFIX + xmlFileName);
if (url == null)
{
fail("Cannot get the resource: " + xmlFileName);
}
return ResourceUtils.getFile(url);
}
private File createZip(ZipEntryContext... zipEntryContexts)
{
File zipFile = TempFileProvider.createTempFile(getClass().getSimpleName(), ".zip");
tempFiles.add(zipFile);
byte[] buffer = new byte[BUFFER_SIZE];
try
{
OutputStream out = new BufferedOutputStream(new FileOutputStream(zipFile), BUFFER_SIZE);
ZipOutputStream zos = new ZipOutputStream(out);
for (ZipEntryContext context : zipEntryContexts)
{
ZipEntry zipEntry = new ZipEntry(context.getZipEntryName());
zos.putNextEntry(zipEntry);
InputStream input = context.getEntryContent();
int len;
while ((len = input.read(buffer)) > 0)
{
zos.write(buffer, 0, len);
}
input.close();
}
zos.closeEntry();
zos.close();
}
catch (IOException ex)
{
fail("couldn't create zip file.");
}
return zipFile;
}
private static class ZipEntryContext
{
private final String zipEntryName;
private final InputStream entryContent;
public ZipEntryContext(String zipEntryName, byte[] zipEntryContent)
{
this.zipEntryName = zipEntryName;
this.entryContent = new ByteArrayInputStream(zipEntryContent);
}
public String getZipEntryName()
{
return this.zipEntryName;
}
public InputStream getEntryContent()
{
return this.entryContent;
}
}
}

View File

@@ -0,0 +1,432 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.alfresco.repo.dictionary.CustomModelServiceImpl;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.rest.api.model.AbstractClassModel;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.api.model.CustomModelConstraint;
import org.alfresco.rest.api.model.CustomModelNamedValue;
import org.alfresco.rest.api.model.CustomModelProperty;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.api.model.CustomModel.ModelStatus;
import org.alfresco.rest.api.tests.RepoService.TestPerson;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.RequestContext;
import org.alfresco.rest.api.tests.client.PublicApiClient.Paging;
import org.alfresco.rest.api.tests.util.RestApiUtil;
import org.alfresco.service.cmr.dictionary.CustomModelDefinition;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.util.Pair;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.junit.After;
import org.junit.Before;
/**
* Base class for CMM API tests
*
* @author Jamal Kaabi-Mofrad
*/
public class BaseCustomModelApiTest extends EnterpriseTestApi
{
public static final String CMM_SCOPE = "private";
public static final String SELECT_PROPS_QS = "?select=props";
public static final String SELECT_STATUS_QS = "?select=status";
public static final String SELECT_ALL = "?select=all";
public static final String SELECT_ALL_PROPS = "?select=allProps";
protected String nonAdminUserName;
protected String customModelAdmin;
protected MutableAuthenticationService authenticationService;
protected PersonService personService;
protected CustomModelService customModelService;
private List<String> users = new ArrayList<>();
@Before
public void setup() throws Exception
{
authenticationService = applicationContext.getBean("authenticationService", MutableAuthenticationService.class);
personService = applicationContext.getBean("personService", PersonService.class);
customModelService = applicationContext.getBean("customModelService", CustomModelService.class);
final AuthorityService authorityService = applicationContext.getBean("authorityService", AuthorityService.class);
this.nonAdminUserName = createUser("nonAdminUser" + System.currentTimeMillis());
this.customModelAdmin = createUser("customModelAdmin" + System.currentTimeMillis());
users.add(nonAdminUserName);
users.add(customModelAdmin);
// Add 'customModelAdmin' user into 'ALFRESCO_MODEL_ADMINISTRATORS' group
transactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
authorityService.addAuthority(CustomModelServiceImpl.GROUP_ALFRESCO_MODEL_ADMINISTRATORS_AUTHORITY, customModelAdmin);
return null;
}
});
}
@After
public void tearDown() throws Exception
{
AuthenticationUtil.setAdminUserAsFullyAuthenticatedUser();
for (final String user : users)
{
transactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
authenticationService.deleteAuthentication(user);
personService.deletePerson(user);
return null;
}
});
}
users.clear();
AuthenticationUtil.clearCurrentSecurityContext();
}
protected String createUser(String username)
{
PersonInfo personInfo = new PersonInfo(username, username, username, "password", null, null, null, null, null, null, null);
TestPerson person = repoService.createUser(personInfo, username, null);
return person.getId();
}
protected HttpResponse post(String url, String runAsUser, String body, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
HttpResponse response = publicApiClient.post(CMM_SCOPE, url, null, null, null, body);
checkStatus(expectedStatus, response.getStatusCode());
return response;
}
protected HttpResponse post(String url, String runAsUser, String body, String queryString, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
if (queryString != null)
{
url += queryString;
}
HttpResponse response = publicApiClient.post(CMM_SCOPE, url, null, null, null, body);
checkStatus(expectedStatus, response.getStatusCode());
return response;
}
protected HttpResponse getAll(String url, String runAsUser, Paging paging, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
Map<String, String> params = (paging == null) ? null : createParams(paging, null);
HttpResponse response = publicApiClient.get(CMM_SCOPE, url, null, null, null, params);
checkStatus(expectedStatus, response.getStatusCode());
return response;
}
protected HttpResponse getSingle(String url, String runAsUser, String entityId, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
HttpResponse response = publicApiClient.get(CMM_SCOPE, url, entityId, null, null, null);
checkStatus(expectedStatus, response.getStatusCode());
return response;
}
protected HttpResponse put(String url, String runAsUser, String entityId, String body, String queryString, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
if (queryString != null)
{
entityId += queryString;
}
HttpResponse response = publicApiClient.put(CMM_SCOPE, url, entityId, null, null, body, null);
checkStatus(expectedStatus, response.getStatusCode());
return response;
}
protected HttpResponse delete(String url, String runAsUser, String entityId, int expectedStatus) throws Exception
{
publicApiClient.setRequestContext(new RequestContext(runAsUser));
HttpResponse response = publicApiClient.delete(CMM_SCOPE, url, entityId, null, null);
checkStatus(expectedStatus, response.getStatusCode());
return response;
}
protected void checkStatus(int expectedStatus, int actualStatus)
{
if (expectedStatus > 0 && expectedStatus != actualStatus)
{
fail("Status code " + actualStatus + " returned, but expected " + expectedStatus);
}
}
protected CustomModel createCustomModel(String modelName, Pair<String, String> namespacePair, ModelStatus status) throws Exception
{
return createCustomModel(modelName, namespacePair, status, "Test model description", null);
}
protected CustomModel createCustomModel(String modelName, Pair<String, String> namespacePair, ModelStatus status, String desc, String author)
throws Exception
{
CustomModel customModel = new CustomModel();
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setDescription(desc);
customModel.setStatus(status);
customModel.setAuthor(author);
// Create the model as a Model Administrator
HttpResponse response = post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
if (author == null)
{
// ignore 'author' in the comparison
compareCustomModels(customModel, returnedModel, "author");
}
else
{
compareCustomModels(customModel, returnedModel);
}
return customModel;
}
protected <T extends AbstractClassModel> T createTypeAspect(Class<T> glazz, String modelName, String typeAspectName, String title, String desc,
String parent) throws Exception
{
AbstractClassModel classModel = null;
String uri = "cmm/" + modelName;
if (glazz.equals(CustomType.class))
{
classModel = new CustomType();
uri += "/types";
}
else
{
classModel = new CustomAspect();
uri += "/aspects";
}
classModel.setName(typeAspectName);
classModel.setDescription(desc);
classModel.setTitle(title);
classModel.setParentName(parent);
// Create type as a Model Administrator
HttpResponse response = post(uri, customModelAdmin, RestApiUtil.toJsonAsString(classModel), 201);
T returnedClassModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), glazz);
compareCustomTypesAspects(classModel, returnedClassModel, "prefixedName");
return returnedClassModel;
}
protected void compareCustomModels(CustomModel expectedModel, CustomModel actualModel, String... excludeFields)
{
boolean result = EqualsBuilder.reflectionEquals(expectedModel, actualModel, excludeFields);
assertTrue("Two models are not equal. Expected:<" + expectedModel.toString() + "> but was:<" + actualModel.toString() + ">", result);
}
protected void compareCustomTypesAspects(AbstractClassModel expectedDetails, AbstractClassModel actualDetails, String... excludeFields)
{
List<CustomModelProperty> expectedProps = expectedDetails.getProperties();
List<CustomModelProperty> actualProps = actualDetails.getProperties();
// Sort them
sortIfnotNull(expectedProps);
sortIfnotNull(actualProps);
boolean propEqualResult = true;
if (expectedProps.size() == actualProps.size())
{
for (int i = 0, size = expectedProps.size(); i < size; i++)
{
boolean equalProp = EqualsBuilder.reflectionEquals(expectedProps.get(i), actualProps.get(i), excludeFields);
if (!equalProp)
{
propEqualResult = false;
break;
}
}
}
else
{
propEqualResult = false;
}
if (excludeFields.length > 0)
{
int size = excludeFields.length;
excludeFields = Arrays.copyOf(excludeFields, size + 1);
excludeFields[size] = "properties";
}
boolean result = EqualsBuilder.reflectionEquals(expectedDetails, actualDetails, excludeFields);
String typesAspects = (expectedDetails instanceof CustomAspect) ? "aspects" : "types";
assertTrue("Two " + typesAspects + " are not equal. Expected:<" + expectedDetails.toString() + "> but was:<" + actualDetails.toString() + ">",
(result && propEqualResult));
}
protected void compareCustomModelConstraints(CustomModelConstraint expectedConstraint, CustomModelConstraint actualConstraint, String... excludeFields)
{
boolean result = EqualsBuilder.reflectionEquals(expectedConstraint, actualConstraint, excludeFields);
assertTrue("Two constraints are not equal. Expected:<" + expectedConstraint.toString() + "> but was:<" + actualConstraint.toString() + ">", result);
}
protected void compareCustomModelProperties(CustomModelProperty expectedProperty, CustomModelProperty actualProperty, String... excludeFields)
{
boolean result = EqualsBuilder.reflectionEquals(expectedProperty, actualProperty, excludeFields);
assertTrue("Two constraints are not equal. Expected:<" + expectedProperty.toString() + "> but was:<" + actualProperty.toString() + ">", result);
}
protected Pair<String, String> getTestNamespaceUriPrefixPair()
{
long timeMillis = System.currentTimeMillis();
String uri = "http://www.alfresco.org/model/testcmmnamespace" + timeMillis + "/1.0";
String prefix = "testcmm" + timeMillis;
return new Pair<String, String>(uri, prefix);
}
protected CustomModelDefinition getModelDefinition(final String modelName)
{
return transactionHelper.doInTransaction(new RetryingTransactionCallback<CustomModelDefinition>()
{
@Override
public CustomModelDefinition execute() throws Throwable
{
return customModelService.getCustomModel(modelName);
}
});
}
protected void sortIfnotNull(List<CustomModelProperty> list)
{
if (list != null && list.size() > 0)
{
Collections.sort(list);
}
}
protected boolean hasNamespaceUri(Collection<NamespaceDefinition> namespaces, String expectedNamespaceUri)
{
for (NamespaceDefinition ns : namespaces)
{
if (ns.getUri().equals(expectedNamespaceUri))
{
return true;
}
}
return false;
}
protected boolean hasNamespacePrefix(Collection<NamespaceDefinition> namespaces, String expectedNamespacePrefix)
{
for (NamespaceDefinition ns : namespaces)
{
if (ns.getPrefix().equals(expectedNamespacePrefix))
{
return true;
}
}
return false;
}
protected CustomModelProperty getProperty(List<CustomModelProperty> properties, String propName)
{
for (CustomModelProperty prop : properties)
{
if (prop.getName().equals(propName))
{
return prop;
}
}
return null;
}
protected CustomModelNamedValue buildNamedValue(String name, String simpleValue, String... listValue)
{
CustomModelNamedValue namedValue = new CustomModelNamedValue();
namedValue.setName(name);
namedValue.setSimpleValue(simpleValue);
if (listValue.length > 0)
{
namedValue.setListValue(Arrays.asList(listValue));
}
return namedValue;
}
protected String getParameterSimpleValue(List<CustomModelNamedValue> params, String paramName)
{
for (CustomModelNamedValue p : params)
{
if (p.getName().equals(paramName))
{
return p.getSimpleValue();
}
}
return null;
}
protected List<String> getParameterListValue(List<CustomModelNamedValue> params, String paramName)
{
for (CustomModelNamedValue p : params)
{
if (p.getName().equals(paramName))
{
return p.getListValue();
}
}
return null;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests;
import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* @author Jamal Kaabi-Mofrad
*/
public class CMMApiTestSuite extends TestSuite
{
/**
* Creates the test suite
*
* @return the test suite
*/
public static Test suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new JUnit4TestAdapter(TestCustomModel.class));
suite.addTest(new JUnit4TestAdapter(TestCustomTypeAspect.class));
suite.addTest(new JUnit4TestAdapter(TestCustomProperty.class));
suite.addTest(new JUnit4TestAdapter(TestCustomConstraint.class));
suite.addTest(new JUnit4TestAdapter(TestCustomModelExport.class));
return suite;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,661 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.api.model.CustomModel.ModelStatus;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient.Paging;
import org.alfresco.rest.api.tests.util.RestApiUtil;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.junit.Test;
/**
* Tests the REST API of the models of the {@link CustomModelService}.
*
* @author Jamal Kaabi-Mofrad
*/
public class TestCustomModel extends BaseCustomModelApiTest
{
@Test
public void testCreateBasicModel() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
CustomModel customModel = new CustomModel();
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setDescription("Test model description");
customModel.setStatus(CustomModel.ModelStatus.DRAFT);
// Try to create the model as a non Admin user
post("cmm", nonAdminUserName, RestApiUtil.toJsonAsString(customModel), 403);
// Create the model as a Model Administrator
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
// Retrieve the created model
HttpResponse response = getSingle("cmm", customModelAdmin, modelName, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
// Check the retrieved model is the expected model.
// Note: since we didn't specify the Author when created the Model,
// we have to exclude it from the objects comparison. Because,
// the system will add the current authenticated user as the author
// of the model, if the Author hasn't been set.
compareCustomModels(customModel, returnedModel, "author");
}
@Test
public void testCreateBasicModel_Invalid() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
CustomModel customModel = new CustomModel();
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
// Test invalid inputs
{
customModel.setName(modelName + "<script>alert('oops')</script>");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400);
customModel.setName("prefix:" + modelName);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid name. Contains ':'
customModel.setName("prefix " + modelName);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid name. Contains space
customModel.setName(modelName);
customModel.setNamespacePrefix(namespacePair.getSecond()+" space");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid prefix. Contains space
customModel.setNamespacePrefix(namespacePair.getSecond()+"invalid/");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid prefix. Contains '/'
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setNamespaceUri(namespacePair.getFirst()+" space");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid URI. Contains space
customModel.setNamespaceUri(namespacePair.getFirst()+"\\");
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // Invalid URI. Contains '\'
}
// Test mandatory properties of the model
{
customModel.setName("");
customModel.setNamespacePrefix(namespacePair.getSecond());
customModel.setNamespaceUri(namespacePair.getFirst());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // name is mandatory
customModel.setName(modelName);
customModel.setNamespaceUri(null);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // namespaceUri is mandatory
customModel.setName(modelName);
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(null);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 400); // namespacePrefix is mandatory
}
// Test duplicate model name
{
// Test create a model with the same name as the bootstrapped model
customModel.setName("contentmodel");
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 409);
// Create the model
customModel.setName(modelName);
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
// Create a duplicate model
// Set a new namespace to make sure the 409 status code is returned
// because of a name conflict rather than namespace URI
namespacePair = getTestNamespaceUriPrefixPair();
customModel.setNamespaceUri(namespacePair.getFirst());
customModel.setNamespacePrefix(namespacePair.getSecond());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 409);
}
// Test duplicate namespaceUri
{
String modelNameTwo = "testModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
CustomModel customModelTwo = new CustomModel();
customModelTwo.setName(modelNameTwo);
customModelTwo.setNamespaceUri(namespacePairTwo.getFirst());
customModelTwo.setNamespacePrefix(namespacePairTwo.getSecond());
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModelTwo), 201);
String modelNameThree = "testModelThree" + System.currentTimeMillis();
Pair<String, String> namespacePairThree = getTestNamespaceUriPrefixPair();
CustomModel customModelThree = new CustomModel();
customModelThree.setName(modelNameThree);
customModelThree.setNamespaceUri(namespacePairTwo.getFirst()); // duplicate URI
customModelThree.setNamespacePrefix(namespacePairThree.getSecond());
// Try to create a model with a namespace uri which has already been used.
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModelThree), 409);
customModelThree.setNamespaceUri(namespacePairThree.getFirst());
customModelThree.setNamespacePrefix(namespacePairTwo.getSecond()); // duplicate prefix
// Try to create a model with a namespace prefix which has already been used.
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModelThree), 409);
}
}
@Test
public void testListBasicModels() throws Exception
{
String modelName_1 = "testModel1" + System.currentTimeMillis();
// Create the model as a Model Administrator
CustomModel customModel_1 = createCustomModel(modelName_1, getTestNamespaceUriPrefixPair(), ModelStatus.DRAFT);
String modelName_2 = "testModel2" + System.currentTimeMillis();
CustomModel customModel_2 = createCustomModel(modelName_2, getTestNamespaceUriPrefixPair(), ModelStatus.DRAFT);
String modelName_3 = "testModel3" + System.currentTimeMillis();
CustomModel customModel_3 = createCustomModel(modelName_3, getTestNamespaceUriPrefixPair(), ModelStatus.DRAFT);
Paging paging = getPaging(0, Integer.MAX_VALUE);
HttpResponse response = getAll("cmm", customModelAdmin, paging, 200);
List<CustomModel> models = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), CustomModel.class);
assertTrue(models.size() >= 3);
assertTrue(models.contains(customModel_1));
assertTrue(models.contains(customModel_2));
assertTrue(models.contains(customModel_3));
}
@Test
public void testActivateCustomModel() throws Exception
{
String modelNameOne = "testActivateModelOne" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
CustomModel customModelOne = createCustomModel(modelNameOne, namespacePair, ModelStatus.DRAFT, "Test model description", "Jane Doe");
// Retrieve the created model and check its status (the default is DRAFT)
HttpResponse response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.DRAFT, returnedModel.getStatus());
// We only want to update the status, so ignore the other properties
CustomModel updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.ACTIVE);
// Try to activate the model as a non Admin user
put("cmm", nonAdminUserName, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 403);
// Activate the model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Check other properties have not been modified
compareCustomModels(customModelOne, returnedModel, "status");
// Try to activate the already activated model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 500);
// Create another Model
String modelNameTwo = "testActivateModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
CustomModel customModelTwo = createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT, null, "John Doe");
// Activate the model as a Model Administrator
customModelTwo.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(customModelTwo), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameTwo, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Check other properties have not been modified
compareCustomModels(customModelTwo, returnedModel, "status");
}
@Test
public void testDeactivateCustomModel() throws Exception
{
String modelNameOne = "testDeactivateModelOne" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
CustomModel customModelOne = createCustomModel(modelNameOne, namespacePair, ModelStatus.ACTIVE, null, "Mark Moe");
// Retrieve the created model and check its status
HttpResponse response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// We only want to update the status (Deactivate), so ignore the other properties
CustomModel updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.DRAFT);
// Try to deactivate the model as a non Admin user
put("cmm", nonAdminUserName, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 403);
// Deactivate the model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.DRAFT, returnedModel.getStatus());
// Check other properties have not been modified
compareCustomModels(customModelOne, returnedModel, "status");
// Try to deactivate the already deactivated model as a Model Administrator
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 500);
// Activate/Deactivate a model with an aspect
{
// Create another Model
final String modelNameTwo = "testDeactivateModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
CustomModel customModelTwo = createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT, null, "Mark Moe");
// Aspect
CustomAspect aspect = new CustomAspect();
aspect.setName("testMarkerAspect");
post("cmm/" + modelNameTwo + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 201);
// Retrieve the created aspect
getSingle("cmm/" + modelNameTwo + "/aspects", customModelAdmin, aspect.getName(), 200);
// Activate the model as a Model Administrator
customModelTwo.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(customModelTwo), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameTwo, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.DRAFT);
// Deactivate the model as a Model Administrator
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
response = getSingle("cmm", customModelAdmin, modelNameTwo, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.DRAFT, returnedModel.getStatus());
}
}
@Test
public void testDeleteCustomModel() throws Exception
{
String modelName = "testDeleteModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
CustomModel customModel = createCustomModel(modelName, namespacePair, ModelStatus.DRAFT, null, "Joe Bloggs");
// Retrieve the created model
HttpResponse response = getSingle("cmm", customModelAdmin, modelName, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
compareCustomModels(customModel, returnedModel);
// Try to delete the model as a non Admin user
delete("cmm", nonAdminUserName, modelName, 403);
// Delete the model as a Model Administrator
delete("cmm", customModelAdmin, modelName, 204);
// Create the model again
post("cmm", customModelAdmin, RestApiUtil.toJsonAsString(customModel), 201);
// Activated the model
CustomModel updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
// Try to delete the active model
delete("cmm", customModelAdmin, modelName, 409);
// Deactivate and then delete the model
updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
delete("cmm", customModelAdmin, modelName, 204);
}
@Test
public void testUpdateBasicModel() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT, "Test model description", null);
//Test update name
CustomModel updatePayload = new CustomModel();
String newName = modelName + "Modified";
updatePayload.setName(newName);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 400); // Cannot update the model name
// Test update the namespace URI (already in-use)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri("http://www.alfresco.org/model/content/1.0");
updatePayload.setNamespacePrefix("newPrefix");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409); // The namespace uri has already been used
// Test update the namespace Prefix (already in-use)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(getTestNamespaceUriPrefixPair().getFirst());
updatePayload.setNamespacePrefix("cm");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409); // The namespace prefix has already been used
// Test update the namespace URI (without sending the namespace prefix)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(getTestNamespaceUriPrefixPair().getFirst());
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 400); // The namespace prefix is mandatory
// Test update the namespace URI only
updatePayload = new CustomModel();
updatePayload.setNamespacePrefix( namespacePair.getSecond());
Pair<String, String> newURI = getTestNamespaceUriPrefixPair();
updatePayload.setNamespaceUri(newURI.getFirst());
HttpResponse response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(newURI.getFirst(), returnedModel.getNamespaceUri());
assertEquals("The namespace prefix shouldn't have changed.", namespacePair.getSecond(), returnedModel.getNamespacePrefix());
// Test update the namespace prefix (without sending the namespace URI)
updatePayload = new CustomModel();
updatePayload.setNamespacePrefix("newPrefix");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 400); // The namespce uri is mandatory
// Test update the namespace prefix only
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(namespacePair.getFirst());
Pair<String, String> newPrefix = getTestNamespaceUriPrefixPair();
updatePayload.setNamespacePrefix( newPrefix.getSecond());
response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(newPrefix.getSecond(), returnedModel.getNamespacePrefix());
assertEquals("The namespace URI shouldn't have changed.", namespacePair.getFirst(), returnedModel.getNamespaceUri());
// Test a valid update
updatePayload = new CustomModel();
Pair<String, String> newNamespacePair = getTestNamespaceUriPrefixPair();
updatePayload.setNamespaceUri(newNamespacePair.getFirst());
updatePayload.setNamespacePrefix(newNamespacePair.getSecond());
updatePayload.setDescription("Test model description Modified");
updatePayload.setAuthor("John Moe");
updatePayload.setStatus(ModelStatus.ACTIVE); // This should be ignored
// Try to update the model as a non Admin user
put("cmm", nonAdminUserName, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 403);
// Update the model as a Model Administrator
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
// Retrieve the updated model
response = getSingle("cmm", customModelAdmin, modelName, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
compareCustomModels(updatePayload, returnedModel, "name", "status");
assertEquals("The model status should only be updated via '?select=status' request.", ModelStatus.DRAFT, returnedModel.getStatus());
// Activate the model as a Model Administrator
updatePayload = new CustomModel();
updatePayload.setStatus(ModelStatus.ACTIVE);
response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), SELECT_STATUS_QS, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Try to update the ACTIVE model's namespace URI
updatePayload = new CustomModel();
newNamespacePair = getTestNamespaceUriPrefixPair();
updatePayload.setNamespaceUri(newNamespacePair.getFirst());
updatePayload.setNamespacePrefix(returnedModel.getNamespacePrefix());
// Cannot update the namespace uri and/or namespace prefix when the model is Active.
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409);
// Try to update the ACTIVE model's namespace Prefix
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(returnedModel.getNamespaceUri());
updatePayload.setNamespacePrefix("myNewPrefix");
// Cannot update the namespace uri and/or namespace prefix when the model is Active.
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 409);
// Test a valid update of an Active model (you can only update desc and author)
updatePayload = new CustomModel();
updatePayload.setNamespaceUri(returnedModel.getNamespaceUri());
updatePayload.setNamespacePrefix(returnedModel.getNamespacePrefix());
updatePayload.setDescription("Test modifying active model description");
updatePayload.setAuthor("Mark Miller");
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
// Retrieve the updated active model
response = getSingle("cmm", customModelAdmin, modelName, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
compareCustomModels(updatePayload, returnedModel, "name", "status");
}
@Test
//SHA-726
public void testUpdateModel_WithAspectsAndTypes() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
// Add type
String typeBaseName = "testTypeBase" + System.currentTimeMillis();
final String typeBaseNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeBaseName;
createTypeAspect(CustomType.class, modelName, typeBaseName, "test typeBase title", null, "cm:content");
// Add aspect
final String aspectName = "testAspect" + System.currentTimeMillis();
final String aspectNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + aspectName;
createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Activate the model
CustomModel modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
// Add another type with 'typeBaseName' as its parent
String childTypeName = "testTypeChild" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, childTypeName, "test typeChild title", "test typeChild Desc", typeBaseNameWithPrefix);
// Add another aspect with 'aspectName' as its parent
final String childAspectName = "testChildAspect" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, childAspectName, "test child aspect title", null, aspectNameWithPrefix);
// Deactivate the model
modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
// Test update the namespace prefix
CustomModel updatePayload = new CustomModel();
String modifiedPrefix = namespacePair.getSecond() + "Modified";
updatePayload.setNamespacePrefix(modifiedPrefix);
updatePayload.setNamespaceUri(namespacePair.getFirst());
HttpResponse response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(modifiedPrefix, returnedModel.getNamespacePrefix());
assertEquals("The namespace URI shouldn't have changed.", namespacePair.getFirst(), returnedModel.getNamespaceUri());
// Test update the namespace URI
updatePayload = new CustomModel();
updatePayload.setNamespacePrefix(modifiedPrefix);
String modifiedURI = namespacePair.getFirst() + "Modified";
updatePayload.setNamespaceUri(modifiedURI);
response = put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(updatePayload), null, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(modifiedURI, returnedModel.getNamespaceUri());
assertEquals("The namespace prefix shouldn't have changed.", modifiedPrefix, returnedModel.getNamespacePrefix());
// Retrieve the child type
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, childTypeName, 200);
CustomType returnedChildType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
final String newTypeParentName = modifiedPrefix + QName.NAMESPACE_PREFIX + typeBaseName;
assertEquals("The parent name prefix should have been updated.", newTypeParentName, returnedChildType.getParentName());
// Retrieve the child aspect
response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, childAspectName, 200);
CustomAspect returnedChildAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
final String newAspectParentName = modifiedPrefix + QName.NAMESPACE_PREFIX + aspectName;
assertEquals("The parent name prefix should have been updated.", newAspectParentName, returnedChildAspect.getParentName());
}
// SHA-808
@Test
public void testModelsCircularDependency() throws Exception
{
// Model One
String modelNameOne = "testModelOne" + System.currentTimeMillis();
Pair<String, String> namespacePairOne = getTestNamespaceUriPrefixPair();
// Create the modelOne as a Model Administrator
createCustomModel(modelNameOne, namespacePairOne, ModelStatus.DRAFT);
// Add typeA_M1 into modelOne
String typeA_M1 = "testTypeA_M1" + System.currentTimeMillis();
final String typeA_M1_WithPrefix = namespacePairOne.getSecond() + QName.NAMESPACE_PREFIX + typeA_M1;
createTypeAspect(CustomType.class, modelNameOne, typeA_M1, "test typeA_M1 title", null, "cm:content");
// Activate modelOne
CustomModel modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
// Add another type into modelOne with 'typeA_M1' as its parent
String typeB_M1 = "testTypeB_M1" + System.currentTimeMillis();
final String typeB_M1_WithPrefix = namespacePairOne.getSecond() + QName.NAMESPACE_PREFIX + typeB_M1;
createTypeAspect(CustomType.class, modelNameOne, typeB_M1, "test typeB_M1 title", "test typeB_M1 Desc", typeA_M1_WithPrefix);
// Model Two
String modelNameTwo = "testModelTwo" + System.currentTimeMillis();
Pair<String, String> namespacePairTwo = getTestNamespaceUriPrefixPair();
// Create the modelTwo as a Model Administrator
createCustomModel(modelNameTwo, namespacePairTwo, ModelStatus.DRAFT);
// Add type1_M2 into modelTwo with 'typeB_M1' (from modelOne) as its parent
String type1_M2 = "testType1_M2" + System.currentTimeMillis();
final String type1_M2_WithPrefix = namespacePairTwo.getSecond() + QName.NAMESPACE_PREFIX + type1_M2;
createTypeAspect(CustomType.class, modelNameTwo, type1_M2, "test type1_M2 title", null, typeB_M1_WithPrefix );
// Activate modelTwo
CustomModel modelTwoStatusPayload = new CustomModel();
modelTwoStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(modelTwoStatusPayload), SELECT_STATUS_QS, 200);
// Test that the API can handle "circular dependency" - (modelOne depends on modelTwo)
{
// Add another type into modelOne with 'type1_M2' (from modelTwo) as its parent
String typeC_M1 = "testTypeC_M1" + System.currentTimeMillis();
CustomType typeC_M1_Payload = new CustomType();
typeC_M1_Payload.setName(typeC_M1);
typeC_M1_Payload.setTitle("test typeC_M1 title");
typeC_M1_Payload.setParentName(type1_M2_WithPrefix); // => 'type1_M2' (from modelTwo)
// Try to create typeC_M1 which has 'circular dependency'
post("cmm/" + modelNameOne + "/types", customModelAdmin, RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation
}
// Model Three
String modelNameThree = "testModelThree" + System.currentTimeMillis();
Pair<String, String> namespacePairThree = getTestNamespaceUriPrefixPair();
// Create the modelThree as a Model Administrator
createCustomModel(modelNameThree, namespacePairThree, ModelStatus.DRAFT);
// Add type1_M3 into modelThree with 'type1_M2' (from modelTwo) as its parent
String type1_M3 = "testType1_M3" + System.currentTimeMillis();
final String type1_M3_WithPrefix = namespacePairThree.getSecond() + QName.NAMESPACE_PREFIX + type1_M3;
createTypeAspect(CustomType.class, modelNameThree, type1_M3, "test type1_M3 title", null, type1_M2_WithPrefix );
// Activate modelThree
CustomModel modelThreeStatusPayload = new CustomModel();
modelThreeStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameThree, RestApiUtil.toJsonAsString(modelThreeStatusPayload), SELECT_STATUS_QS, 200);
// Test that the API can handle "circular dependency" - (modelOne depends on modelThree)
{
// Add another type into modelOne with 'type1_M3' (from modelThree) as its parent
String typeC_M1 = "testTypeC_M1" + System.currentTimeMillis();
CustomType typeC_M1_Payload = new CustomType();
typeC_M1_Payload.setName(typeC_M1);
typeC_M1_Payload.setTitle("test typeC_M1 title");
typeC_M1_Payload.setParentName(type1_M3_WithPrefix); // => 'type1_M3' (from modelThree)
// Try to create typeC_M1 which has 'circular dependency'
post("cmm/" + modelNameOne + "/types", customModelAdmin, RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation
}
// Model Three
String modelNameFour = "testModelFour" + System.currentTimeMillis();
Pair<String, String> namespacePairFour = getTestNamespaceUriPrefixPair();
// Create the modelFour as a Model Administrator
createCustomModel(modelNameFour, namespacePairFour, ModelStatus.DRAFT);
// Add type1_M4 into modelFour with 'type1_M3' (from modelThree) as its parent
String type1_M4 = "testType1_M4" + System.currentTimeMillis();
final String type1_M4_WithPrefix = namespacePairFour.getSecond() + QName.NAMESPACE_PREFIX + type1_M4;
createTypeAspect(CustomType.class, modelNameFour, type1_M4, "test type1_M4 title", null, type1_M3_WithPrefix );
// Activate modelFour
CustomModel modelFourStatusPayload = new CustomModel();
modelFourStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameFour, RestApiUtil.toJsonAsString(modelFourStatusPayload), SELECT_STATUS_QS, 200);
// Test that the API can handle "circular dependency" - (modelOne depends on modelFour)
{
// Add another type into modelOne with 'type1_M4' (from modelFour) as its parent
String typeC_M1 = "testTypeC_M1" + System.currentTimeMillis();
CustomType typeC_M1_Payload = new CustomType();
typeC_M1_Payload.setName(typeC_M1);
typeC_M1_Payload.setTitle("test typeC_M1 title");
typeC_M1_Payload.setParentName(type1_M4_WithPrefix); // => 'type1_M4' (from modelFour)
// Try to create typeC_M1 which has 'circular dependency'
post("cmm/" + modelNameOne + "/types", customModelAdmin, RestApiUtil.toJsonAsString(typeC_M1_Payload), 409); //Constraint violation
}
// Test that the API can handle "circular dependency" - (modelTwo depends on modelFour)
{
// Add another type into modelTwo with 'type1_M4' (from modelFour) as its parent
String type2_M2 = "testType2_M2" + System.currentTimeMillis();
CustomType type2_M2_Payload = new CustomType();
type2_M2_Payload.setName(type2_M2);
type2_M2_Payload.setTitle("test type2_M2 title");
type2_M2_Payload.setParentName(type1_M4_WithPrefix); // => 'type1_M4' (from modelFour)
// Try to create type2_M2 which has 'circular dependency'
post("cmm/" + modelNameTwo + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type2_M2_Payload), 409); //Constraint violation
}
}
}

View File

@@ -0,0 +1,137 @@
package org.alfresco.rest.api.tests;
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Set;
import org.alfresco.repo.dictionary.CMMDownloadTestUtil;
import org.alfresco.rest.api.model.CustomModelDownload;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.api.model.CustomModel.ModelStatus;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.util.RestApiUtil;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.cmr.download.DownloadStatus;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair;
import org.junit.Test;
/**
* Tests REST API download of the {@link CustomModelService}.
*
* @author Jamal Kaabi-Mofrad
*/
public class TestCustomModelExport extends BaseCustomModelApiTest
{
private static final long PAUSE_TIME = 1000;
private CMMDownloadTestUtil downloadTestUtil;
@Override
public void setup() throws Exception
{
super.setup();
this.downloadTestUtil = new CMMDownloadTestUtil(applicationContext);
}
@Override
public void tearDown() throws Exception
{
this.downloadTestUtil.cleanup();
super.tearDown();
}
@Test
public void testCreateDownload() throws Exception
{
final String modelName = "testModel" + System.currentTimeMillis();
final String modelExportFileName = modelName + ".xml";
final String shareExtExportFileName = "CMM_" + modelName + "_module.xml";
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT, null, "Mark Moe");
// Add type
String typeBaseName = "testTypeBase" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, typeBaseName, "test typeBase title", "test typeBase Desc", "cm:content");
// Create Share extension module
downloadTestUtil.createShareExtModule(modelName);
// Try to create download the model as a non Admin user
post("cmm/" + modelName + "/download", nonAdminUserName, RestApiUtil.toJsonAsString(new CustomModelDownload()), getExtModuleQS(false), 403);
// Create download for custom model only
HttpResponse response = post("cmm/" + modelName + "/download", customModelAdmin, RestApiUtil.toJsonAsString(new CustomModelDownload()), getExtModuleQS(false), 201);
CustomModelDownload returnedDownload = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModelDownload.class);
assertNotNull(returnedDownload);
assertNotNull(returnedDownload.getNodeRef());
NodeRef downloadNode = new NodeRef(returnedDownload.getNodeRef());
DownloadStatus status = downloadTestUtil.getDownloadStatus(downloadNode);
while (status.getStatus() == DownloadStatus.Status.PENDING)
{
Thread.sleep(PAUSE_TIME);
status = downloadTestUtil.getDownloadStatus(downloadNode);
}
Set<String> entries = downloadTestUtil.getDownloadEntries(downloadNode);
assertEquals(1, entries.size());
String modelEntry = downloadTestUtil.getDownloadEntry(entries, modelExportFileName);
assertNotNull(modelEntry);
assertEquals(modelEntry, modelExportFileName);
// Create download for custom model and its share extension module
response = post("cmm/" + modelName + "/download", customModelAdmin, RestApiUtil.toJsonAsString(new CustomModelDownload()), getExtModuleQS(true), 201);
returnedDownload = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModelDownload.class);
assertNotNull(returnedDownload);
assertNotNull(returnedDownload.getNodeRef());
downloadNode = new NodeRef(returnedDownload.getNodeRef());
status = downloadTestUtil.getDownloadStatus(downloadNode);
while (status.getStatus() == DownloadStatus.Status.PENDING)
{
Thread.sleep(PAUSE_TIME);
status = downloadTestUtil.getDownloadStatus(downloadNode);
}
entries = downloadTestUtil.getDownloadEntries(downloadNode);
assertEquals(2, entries.size());
modelEntry = downloadTestUtil.getDownloadEntry(entries, modelExportFileName);
assertNotNull(modelEntry);
assertEquals(modelEntry, modelExportFileName);
String shareExtEntry = downloadTestUtil.getDownloadEntry(entries, shareExtExportFileName);
assertNotNull(shareExtEntry);
assertEquals(shareExtEntry, shareExtExportFileName);
}
private String getExtModuleQS(boolean withShareExtModule)
{
return "?extModule=" + withShareExtModule;
}
}

View File

@@ -0,0 +1,700 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.alfresco.repo.dictionary.Facetable;
import org.alfresco.repo.dictionary.IndexTokenisationMode;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.api.model.CustomModelConstraint;
import org.alfresco.rest.api.model.CustomModelNamedValue;
import org.alfresco.rest.api.model.CustomModelProperty;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.api.model.CustomModel.ModelStatus;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.util.RestApiUtil;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.junit.Test;
/**
* Tests the REST API of the properties of the {@link CustomModelService}.
*
* @author Jamal Kaabi-Mofrad
*/
public class TestCustomProperty extends BaseCustomModelApiTest
{
@Test
public void testCreateProperties() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
{
// Create aspect
String aspectName = "testAspect1" + System.currentTimeMillis();
CustomAspect aspect = createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Update the Aspect by adding property
CustomAspect payload = new CustomAspect();
String aspectPropName = "testAspect1Prop1" + System.currentTimeMillis();
CustomModelProperty aspectProp = new CustomModelProperty();
aspectProp.setName(aspectPropName);
aspectProp.setTitle("property title");
aspectProp.setMultiValued(true);
aspectProp.setIndexed(true);
aspectProp.setFacetable(Facetable.TRUE);
aspectProp.setIndexTokenisationMode(IndexTokenisationMode.BOTH);
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(aspectProp);
payload.setProperties(props);
// Try to update the aspect as a non Admin user
put("cmm/" + modelName + "/aspects", nonAdminUserName, aspectName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 403);
// Try to update the aspect as a Model Administrator
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 400); // Type name is mandatory
// Add the mandatory aspect name to the payload
payload.setName(aspectName);
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 200);
// Retrieve the updated aspect
HttpResponse response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspect.getName(), 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
// Check the aspect's added property
assertEquals(1, returnedAspect.getProperties().size());
CustomModelProperty customModelProperty = returnedAspect.getProperties().get(0);
assertEquals(aspectPropName, customModelProperty.getName());
assertEquals("property title", customModelProperty.getTitle());
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + aspectPropName, customModelProperty.getPrefixedName());
assertEquals("Default data type is 'd:text'.", "d:text", customModelProperty.getDataType());
assertNull(customModelProperty.getDescription());
assertTrue(customModelProperty.isMultiValued());
assertFalse(customModelProperty.isMandatory());
assertFalse(customModelProperty.isMandatoryEnforced());
assertNull(customModelProperty.getDefaultValue());
assertTrue(customModelProperty.isIndexed());
assertEquals(Facetable.TRUE, customModelProperty.getFacetable());
assertEquals(IndexTokenisationMode.BOTH, customModelProperty.getIndexTokenisationMode());
// Test duplicate property name
aspectProp = new CustomModelProperty();
aspectProp.setName(aspectPropName); // Existing name
aspectProp.setTitle("new property title");
props = new ArrayList<>(1);
props.add(aspectProp);
payload.setProperties(props);
// Try to update the aspect as a Model Administrator
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 409); // property name already exists
}
{
// Create type
String typeName = "testType1" + System.currentTimeMillis();
CustomType type = createTypeAspect(CustomType.class, modelName, typeName, "test type1 title", "test type1 Desc", "cm:content");
// Update the Type by adding property
CustomType payload = new CustomType();
String typePropName = "testType1Prop1" + System.currentTimeMillis();
CustomModelProperty typeProp = new CustomModelProperty();
typeProp.setName(typePropName);
typeProp.setTitle("property title");
typeProp.setDataType("d:int");
typeProp.setIndexed(false);
typeProp.setFacetable(Facetable.FALSE);
typeProp.setIndexTokenisationMode(IndexTokenisationMode.FALSE);
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(typeProp);
payload.setProperties(props);
// Try to update the type as a non Admin user
put("cmm/" + modelName + "/types", nonAdminUserName, typeName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 403);
// Try to update the type as a Model Administrator
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 400); // Type name is mandatory
// Add the mandatory type name to the payload
payload.setName(typeName);
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 200);
// Retrieve the updated type
HttpResponse response = getSingle("cmm/" + modelName + "/types", customModelAdmin, type.getName(), 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
// Check the type's added property
assertEquals(1, returnedType.getProperties().size());
CustomModelProperty customModelProperty = returnedType.getProperties().get(0);
assertEquals(typePropName, customModelProperty.getName());
assertEquals("property title", customModelProperty.getTitle());
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typePropName, customModelProperty.getPrefixedName());
assertEquals("d:int", customModelProperty.getDataType());
assertNull(customModelProperty.getDescription());
assertFalse(customModelProperty.isMultiValued());
assertFalse(customModelProperty.isMandatory());
assertFalse(customModelProperty.isMandatoryEnforced());
assertNull(customModelProperty.getDefaultValue());
assertFalse(customModelProperty.isIndexed());
assertEquals(Facetable.FALSE, customModelProperty.getFacetable());
assertEquals(IndexTokenisationMode.FALSE, customModelProperty.getIndexTokenisationMode());
// Retrieve the updated type with all the properties (include inherited)
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, type.getName()+SELECT_ALL_PROPS, 200);
returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
assertEquals(3, returnedType.getProperties().size());
// Check for the inherited properties
assertNotNull(getProperty(returnedType.getProperties(), "content")); // cm:content
assertNotNull(getProperty(returnedType.getProperties(), "name")); // cm:name
// Create another property and set all of its attributes
payload = new CustomType();
payload.setName(typeName);
String typePropName2 = "testType1Prop2" + System.currentTimeMillis();
typeProp = new CustomModelProperty();
typeProp.setName(typePropName2);
typeProp.setTitle("property2 title");
typeProp.setDescription("property2 desciption");
typeProp.setDataType("d:int");
typeProp.setDefaultValue("0");
typeProp.setMultiValued(false);
typeProp.setMandatory(true);
typeProp.setMandatoryEnforced(true);
props = new ArrayList<>(1);
props.add(typeProp);
payload.setProperties(props);
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 200);
// Retrieve the updated type
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, type.getName(), 200);
returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
// Check the type's added property
assertEquals(2, returnedType.getProperties().size());
customModelProperty = getProperty(returnedType.getProperties(), typePropName2);
assertNotNull(customModelProperty);
assertEquals(typePropName2, customModelProperty.getName());
assertEquals("property2 title", customModelProperty.getTitle());
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typePropName2, customModelProperty.getPrefixedName());
assertEquals("d:int", customModelProperty.getDataType());
assertEquals("property2 desciption", customModelProperty.getDescription());
assertFalse(customModelProperty.isMultiValued());
assertTrue(customModelProperty.isMandatory());
assertTrue(customModelProperty.isMandatoryEnforced());
assertEquals("0", customModelProperty.getDefaultValue());
// Test duplicate property name
typeProp = new CustomModelProperty();
typeProp.setName(typePropName2); // Existing name
typeProp.setTitle("new property title");
typeProp.setDataType("d:text");
props = new ArrayList<>(1);
props.add(typeProp);
payload.setProperties(props);
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 409); // property name already exists
}
}
@Test
public void testDeleteProperty() throws Exception
{
String modelName = "testModelDeleteProp" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
/*
* Create aspect and update it by adding two properties
*/
String aspectName = "testAspect1" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Update the Aspect by adding property - property one
CustomAspect aspectPayload = new CustomAspect();
aspectPayload.setName(aspectName);
String aspectPropNameOne = "testAspect1Prop1" + System.currentTimeMillis();
CustomModelProperty aspectPropOne = new CustomModelProperty();
aspectPropOne.setName(aspectPropNameOne);
aspectPropOne.setTitle("aspect property one title");
aspectPropOne.setMultiValued(true);
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(aspectPropOne);
aspectPayload.setProperties(props);
// create property one
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 200);
// Update the Aspect by adding another property - property two
aspectPayload = new CustomAspect();
aspectPayload.setName(aspectName);
String aspectPropNameTwo = "testAspect1Prop2" + System.currentTimeMillis();
CustomModelProperty aspectPropTwo = new CustomModelProperty();
aspectPropTwo.setName(aspectPropNameTwo);
aspectPropTwo.setTitle("aspect property two title");
aspectPropTwo.setMandatory(true);
aspectPropTwo.setDataType("d:int");
aspectPropTwo.setDefaultValue("1");
props = new ArrayList<>(1);
props.add(aspectPropTwo);
aspectPayload.setProperties(props);
// create property two
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 200);
// Retrieve the updated aspect
HttpResponse response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
// Check the aspect's added properties
assertEquals(2, returnedAspect.getProperties().size());
/*
* Create type and update it by adding two properties
*/
String typeName = "testType1" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, typeName, "test type1 title", null, "cm:content");
// Update the Type by adding property - property one
CustomType typePayload = new CustomType();
typePayload.setName(typeName);
String typePropNameOne = "testType1Prop1" + System.currentTimeMillis();
CustomModelProperty typePropOne = new CustomModelProperty();
typePropOne.setName(typePropNameOne);
typePropOne.setTitle("type property one title");
props = new ArrayList<>(1);
props.add(typePropOne);
typePayload.setProperties(props);
// create property one
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), SELECT_PROPS_QS, 200);
// Update the Type by adding another property - property two
typePayload = new CustomType();
typePayload.setName(typeName);
// Create inline MINMAX constraint
CustomModelConstraint inlineMinMaxConstraint = new CustomModelConstraint();
inlineMinMaxConstraint.setType("MINMAX");
inlineMinMaxConstraint.setTitle("test MINMAX title");
// Create the MinMax constraint's parameters
List<CustomModelNamedValue> parameters = new ArrayList<>(2);
parameters.add(buildNamedValue("maxValue", "100.0"));
parameters.add(buildNamedValue("minValue", "0.0"));
// Add the parameters into the constraint
inlineMinMaxConstraint.setParameters(parameters);
String typePropNameTwo = "testType1Prop2" + System.currentTimeMillis();
CustomModelProperty typePropTwo = new CustomModelProperty();
typePropTwo.setName(typePropNameTwo);
typePropTwo.setTitle("type property two title");
typePropTwo.setDataType("d:int");
typePropTwo.setConstraints(Arrays.asList(inlineMinMaxConstraint)); // add the inline constraint
props = new ArrayList<>(1);
props.add(typePropTwo);
typePayload.setProperties(props);
// create property one
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), SELECT_PROPS_QS, 200);
// Retrieve the updated type
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
// Check the type's added properties
assertEquals(2, returnedType.getProperties().size());
// Delete aspect's property one - model is inactive
{
final String deletePropOneAspectQS = getPropDeleteUpdateQS(aspectPropNameOne, true);
// Try to delete propertyOne from aspect
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, null, deletePropOneAspectQS, 400); // missing payload
CustomAspect deletePropAspectPayload = new CustomAspect();
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(deletePropAspectPayload), deletePropOneAspectQS, 400); // missing aspect name
deletePropAspectPayload.setName(aspectName);
put("cmm/" + modelName + "/aspects", nonAdminUserName, aspectName, RestApiUtil.toJsonAsString(deletePropAspectPayload), deletePropOneAspectQS, 403); // unauthorised
// Delete as a Model Administrator
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(deletePropAspectPayload), deletePropOneAspectQS, 200);
// Check the property has been deleted
response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 200);
returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
assertEquals(1, returnedAspect.getProperties().size());
assertFalse("Property one should have been deleted.", aspectPropNameOne.equals(returnedAspect.getProperties().get(0).getName()));
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(deletePropAspectPayload), deletePropOneAspectQS, 404); //Not found
}
// Delete type's property two - model is inactive
{
final String deletePropTwoTypeQS = getPropDeleteUpdateQS(typePropNameTwo, true);
// Try to delete propertyOne from type
put("cmm/" + modelName + "/types", customModelAdmin, typeName, null, deletePropTwoTypeQS, 400); // missing payload
CustomType deletePropTypePayload = new CustomType();
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(deletePropTypePayload), deletePropTwoTypeQS,
400); // missing type name
deletePropTypePayload.setName(typeName);
put("cmm/" + modelName + "/types", nonAdminUserName, typeName, RestApiUtil.toJsonAsString(deletePropTypePayload), deletePropTwoTypeQS, 403); // unauthorised
// Delete as a Model Administrator
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(deletePropTypePayload), deletePropTwoTypeQS, 200);
// Check the property has been deleted
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 200);
returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
assertEquals(1, returnedType.getProperties().size());
assertFalse("Property two should have been deleted.", typePropNameTwo.equals(returnedType.getProperties().get(0).getName()));
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(deletePropTypePayload), deletePropTwoTypeQS, 404); //Not found
}
// Note: at the time of writing, we can't delete a property of an active model, as ModelValidatorImpl.validateIndexedProperty depends on Solr
}
@Test
public void testUpdateProperty() throws Exception
{
String modelName = "testModelUpdateProp" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
/*
* Create aspect and update it by adding a property
*/
String aspectName = "testAspect1" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Update the Aspect by adding property
CustomAspect aspectPayload = new CustomAspect();
aspectPayload.setName(aspectName);
String aspectPropName = "testAspect1Prop" + System.currentTimeMillis();
CustomModelProperty aspectProp = new CustomModelProperty();
aspectProp.setName(aspectPropName);
aspectProp.setTitle("aspect property title");
aspectProp.setMultiValued(true);
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(aspectProp);
aspectPayload.setProperties(props);
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 200);
// Retrieve the updated aspect
HttpResponse response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
// Check the aspect's added property
assertEquals(1, returnedAspect.getProperties().size());
/*
* Create type and update it by adding a property
*/
String typeName = "testType1" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, typeName, "test type1 title", null, "cm:content");
// Update the Type by adding property - property one
CustomType typePayload = new CustomType();
typePayload.setName(typeName);
// Create inline MINMAX constraint
CustomModelConstraint inlineMinMaxConstraint = new CustomModelConstraint();
inlineMinMaxConstraint.setType("MINMAX");
inlineMinMaxConstraint.setTitle("test MINMAX title");
// Create the MinMax constraint's parameters
List<CustomModelNamedValue> parameters = new ArrayList<>(2);
parameters.add(buildNamedValue("maxValue", "100.0"));
parameters.add(buildNamedValue("minValue", "0.0"));
// Add the parameters into the constraint
inlineMinMaxConstraint.setParameters(parameters);
String typePropName = "testType1Prop" + System.currentTimeMillis();
CustomModelProperty typeProp = new CustomModelProperty();
typeProp.setName(typePropName);
typeProp.setDataType("d:int");
typeProp.setTitle("type property title");
typeProp.setDefaultValue("0");
typeProp.setConstraints(Arrays.asList(inlineMinMaxConstraint)); // add the inline constraint
props = new ArrayList<>(1);
props.add(typeProp);
typePayload.setProperties(props);
// create property
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), SELECT_PROPS_QS, 200);
// Retrieve the updated type
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
// Check the type's added property
assertEquals(1, returnedType.getProperties().size());
// Update aspect's property - model is inactive
{
final String updatePropOneAspectQS = getPropDeleteUpdateQS(aspectPropName, false);
// Try to update property from aspect
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, null, updatePropOneAspectQS, 400); // missing payload
CustomAspect updatePropAspectPayload = new CustomAspect();
CustomModelProperty propertyAspect = new CustomModelProperty();
propertyAspect.setTitle("new Title");
propertyAspect.setDescription("new Desc");
propertyAspect.setDataType("d:int"); // the original value was d:text
propertyAspect.setMultiValued(false); // the original value was true
propertyAspect.setMandatory(true); // the original value was false
propertyAspect.setDefaultValue("10");
List<CustomModelProperty> modifiedProp = new ArrayList<>(1);
modifiedProp.add(propertyAspect);
updatePropAspectPayload.setProperties(modifiedProp);
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(updatePropAspectPayload), updatePropOneAspectQS, 400); // missing aspect name
// set a random name
updatePropAspectPayload.setName(aspectName + System.currentTimeMillis());
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(updatePropAspectPayload), updatePropOneAspectQS, 404); // Aspect not found
// set the correct name
updatePropAspectPayload.setName(aspectName);
// the requested property name dose not match the payload
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(updatePropAspectPayload), updatePropOneAspectQS, 400);
// set the property name that matches the requested property
propertyAspect.setName(aspectPropName);
put("cmm/" + modelName + "/aspects", nonAdminUserName, aspectName, RestApiUtil.toJsonAsString(updatePropAspectPayload), updatePropOneAspectQS, 403); // unauthorised
// Update as a Model Administrator
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(updatePropAspectPayload), updatePropOneAspectQS, 200);
// Check the property has been updated
response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 200);
returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
assertEquals(1, returnedAspect.getProperties().size());
CustomModelProperty modifiedAspectProperty = returnedAspect.getProperties().get(0);
compareCustomModelProperties(propertyAspect, modifiedAspectProperty, "prefixedName", "indexTokenisationMode");
}
// Activate the model
CustomModel statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// Update type's property - model is active
{
final String updatePropTwoTypeQS = getPropDeleteUpdateQS(typePropName, false);
CustomType updatePropTypePayload = new CustomType();
updatePropTypePayload.setName(typeName);
CustomModelProperty propertyType = new CustomModelProperty();
propertyType.setName(typePropName);
propertyType.setTitle("new Title");
propertyType.setDescription("new Desc");
propertyType.setDataType("d:long"); // the original value was d:int
propertyType.setDefaultValue("5");
List<CustomModelProperty> modifiedProp = new ArrayList<>(1);
modifiedProp.add(propertyType);
updatePropTypePayload.setProperties(modifiedProp);
// Unauthorised
put("cmm/" + modelName + "/types", nonAdminUserName, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 403);
// Try to update an active model as a Model Administrator - Cannot change the data type of the property of an active model
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 409);
// Set the data type with its original value
propertyType.setDataType("d:int");
propertyType.setMultiValued(true);// the original value was false
// Cannot change the multi-valued option of the property of an active model
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 409);
propertyType.setMultiValued(false);
propertyType.setMandatory(true);// the original value was false
// Cannot change the mandatory option of the property of an active model
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 409);
propertyType.setMandatory(false);
propertyType.setMandatoryEnforced(true);// the original value was false
// Cannot change the mandatory-enforced option of the property of an active model
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 409);
// Set the mandatory-enforced with its original value
propertyType.setMandatoryEnforced(false);
// Update the MinMax constraint's parameters
parameters = new ArrayList<>(2);
parameters.add(buildNamedValue("maxValue", "120.0")); // the original value was 100.0
parameters.add(buildNamedValue("minValue", "20.0")); // the original value was 0.0
// Add the parameters into the constraint
inlineMinMaxConstraint.setParameters(parameters);
propertyType.setConstraints(Arrays.asList(inlineMinMaxConstraint)); // add the updated inline constraint
// Try to Update - constraint violation. The default value is 5 which is not in the MinMax range [20, 120]
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 409);
propertyType.setDefaultValue("25"); // we changed the MinMax constraint to be [20, 120]
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 200);
// Check the property has been updated
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 200);
returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
assertEquals(1, returnedType.getProperties().size());
CustomModelProperty modifiedTypeProperty = returnedType.getProperties().get(0);
assertEquals("new Title", modifiedTypeProperty.getTitle());
assertEquals("new Desc", modifiedTypeProperty.getDescription());
assertEquals("25", modifiedTypeProperty.getDefaultValue());
assertEquals("Shouldn't be able to change the data type of the property of an active model." ,"d:int", modifiedTypeProperty.getDataType());
assertFalse(modifiedTypeProperty.isMandatory());
assertFalse(modifiedTypeProperty.isMultiValued());
assertFalse(modifiedTypeProperty.isMandatoryEnforced());
assertEquals(1, modifiedTypeProperty.getConstraints().size());
CustomModelConstraint modifiedConstraint = modifiedTypeProperty.getConstraints().get(0);
assertEquals("MINMAX", modifiedConstraint.getType());
assertEquals("120.0", getParameterSimpleValue(modifiedConstraint.getParameters(), "maxValue"));
assertEquals("20.0", getParameterSimpleValue(modifiedConstraint.getParameters(), "minValue"));
// Change the constraint type and parameter
inlineMinMaxConstraint.setType("LENGTH");
inlineMinMaxConstraint.setTitle("test LENGTH title");
parameters = new ArrayList<>(2);
parameters.add(buildNamedValue("maxLength", "256"));
parameters.add(buildNamedValue("minLength", "0"));
// Add the parameters into the constraint
inlineMinMaxConstraint.setParameters(parameters);
propertyType.setConstraints(Arrays.asList(inlineMinMaxConstraint));
// LENGTH can only be used with textual data type
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 400);
//update the property by removing the constraint
propertyType.setConstraints(Collections.<CustomModelConstraint>emptyList());
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(updatePropTypePayload), updatePropTwoTypeQS, 200);
response = getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 200);
returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
assertEquals(1, returnedType.getProperties().size());
modifiedTypeProperty = returnedType.getProperties().get(0);
assertEquals(0, modifiedTypeProperty.getConstraints().size());
}
}
@Test
public void testValidatePropertyDefaultValue() throws Exception
{
String modelName = "testModelPropDefaultValue" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
/*
* Create aspect and update it by adding a property
*/
String aspectName = "testAspect1" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Update the Aspect by adding property
CustomAspect aspectPayload = new CustomAspect();
aspectPayload.setName(aspectName);
String aspectPropName = "testAspectProp" + System.currentTimeMillis();
final String updatePropAspectQS = getPropDeleteUpdateQS(aspectPropName, false);
CustomModelProperty aspectProp = new CustomModelProperty();
aspectProp.setName(aspectPropName);
aspectProp.setTitle("aspect property title");
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(aspectProp);
aspectPayload.setProperties(props);
// d:int tests
{
aspectProp.setDataType("d:int");
aspectProp.setDefaultValue(" ");// space
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
aspectProp.setDefaultValue("abc"); // text
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
aspectProp.setDefaultValue("1.0"); // double
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
aspectProp.setDefaultValue("1,2,3"); // text
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
}
// d:float tests
{
aspectProp.setDataType("d:float");
aspectProp.setDefaultValue(" ");// space
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
aspectProp.setDefaultValue("abc"); // text
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
aspectProp.setDefaultValue("1,2,3"); // text
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 400);
aspectProp.setDefaultValue("1.0"); // float
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), SELECT_PROPS_QS, 200);
aspectProp.setDefaultValue("1.0f"); // float - update
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 200);
aspectProp.setDefaultValue("1.0d"); // double - update
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 200);
}
// d:boolean tests
{
aspectProp.setDataType("d:boolean");
aspectProp.setDefaultValue(" ");// space
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 400);
aspectProp.setDefaultValue("abc"); // text
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 400);
aspectProp.setDefaultValue("1"); // number
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 400);
aspectProp.setDefaultValue("true"); // valid value
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 200);
aspectProp.setDefaultValue("false"); // valid value
// create property
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), updatePropAspectQS, 200);
}
}
private String getPropDeleteUpdateQS(String propName, boolean isDelete)
{
String req = (isDelete ? "&delete=" : "&update=");
return SELECT_PROPS_QS + req + propName;
}
}

View File

@@ -0,0 +1,638 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.alfresco.repo.dictionary.Facetable;
import org.alfresco.repo.dictionary.IndexTokenisationMode;
import org.alfresco.rest.api.model.CustomAspect;
import org.alfresco.rest.api.model.CustomModel;
import org.alfresco.rest.api.model.CustomModelProperty;
import org.alfresco.rest.api.model.CustomType;
import org.alfresco.rest.api.model.CustomModel.ModelStatus;
import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient.Paging;
import org.alfresco.rest.api.tests.util.RestApiUtil;
import org.alfresco.service.cmr.dictionary.CustomModelDefinition;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.cmr.dictionary.NamespaceDefinition;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.junit.Test;
/**
* Tests the REST API of the types and aspects of the {@link CustomModelService}.
*
* @author Jamal Kaabi-Mofrad
*/
public class TestCustomTypeAspect extends BaseCustomModelApiTest
{
@Test
public void testCreateAspectsAndTypes_ExistingModel() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
final String aspectName = "testAspect1" + System.currentTimeMillis();
{
// Add aspect
CustomAspect aspect = new CustomAspect();
aspect.setName(aspectName);
// Try to create aspect as a non Admin user
post("cmm/" + modelName + "/aspects", nonAdminUserName, RestApiUtil.toJsonAsString(aspect), 403);
// Set the aspect's parent with a type name!
aspect.setParentName("cm:content");
// Try to create an invalid aspect as a Model Administrator
post("cmm/" + modelName + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 409);
// Create aspect as a Model Administrator
aspect.setParentName(null);
post("cmm/" + modelName + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 201);
// Create the aspect again - duplicate name
post("cmm/" + modelName + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 409);
// Retrieve the created aspect
HttpResponse response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspect.getName(), 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
compareCustomTypesAspects(aspect, returnedAspect, "prefixedName");
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + aspectName, returnedAspect.getPrefixedName());
}
String typeName = "testType" + System.currentTimeMillis();
{
// Add type
CustomType type = new CustomType();
type.setName(typeName);
type.setDescription("test type Desc");
type.setTitle("test type title");
type.setParentName("cm:content");
// Try to create type as a non Admin user
post("cmm/" + modelName + "/types", nonAdminUserName, RestApiUtil.toJsonAsString(type), 403);
// Set the type's parent with an aspect name!
type.setParentName("cm:titled");
// Try to create an invalid type as a Model Administrator
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 409);
// Create type as a Model Administrator
type.setParentName("cm:content");
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 201);
// Create the type again - duplicate name
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 409);
// Retrieve the created type
HttpResponse response = getSingle("cmm/" + modelName + "/types", customModelAdmin, type.getName(), 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
compareCustomTypesAspects(type, returnedType, "prefixedName");
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeName, returnedType.getPrefixedName());
// for now this is the simplest way to check for the imported namespaces
CustomModelDefinition modelDef = getModelDefinition(modelName);
assertNotNull(modelDef);
Collection<NamespaceDefinition> importedNamespaces = modelDef.getImportedNamespaces();
assertTrue(hasNamespaceUri(importedNamespaces, "http://www.alfresco.org/model/content/1.0"));
assertTrue(hasNamespacePrefix(importedNamespaces, "cm"));
}
// Existing name
{
// Add aspect
CustomAspect aspect = new CustomAspect();
// Set the aspect name with an existing type name. The model
// cannot have a type and an aspect with the same name.
aspect.setName(typeName);
post("cmm/" + modelName + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 409);
CustomType type = new CustomType();
// Set the type name with an existing aspect name
type.setName(aspectName);
type.setParentName("cm:content");
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 409);
}
}
@Test
public void testCreateModel_WithAspectsAndTypes_Invalid() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
// Add type
{
final String typeURL = "cmm/" + modelName + "/types";
CustomType type = new CustomType();
type.setName(null);
type.setDescription("test type Desc");
// Try to create a model with an invalid type name (null)
post(typeURL, customModelAdmin, RestApiUtil.toJsonAsString(type), 400);
// Try to create a model with an invalid type name (name contains ':')
type.setName("prefix:someTypename");
post(typeURL, customModelAdmin, RestApiUtil.toJsonAsString(type), 400);
// Try to create a model with an invalid type name (name is empty)
type.setName("");
post(typeURL, customModelAdmin, RestApiUtil.toJsonAsString(type), 400);
// Try to create a model with an invalid type name (name contains '<')
type.setName("testType<name");
post(typeURL, customModelAdmin, RestApiUtil.toJsonAsString(type), 400);
}
// Add aspect
{
final String aspectURL = "cmm/" + modelName + "/aspects";
CustomAspect aspect = new CustomAspect();
aspect.setName(null);
aspect.setTitle("test aspect title");
// Try to create a model with an invalid aspect name (null)
post(aspectURL, customModelAdmin, RestApiUtil.toJsonAsString(aspect), 400);
// Try to create a model with an invalid aspect name (name contains ':')
aspect.setName("prefix:someAspectname");
post(aspectURL, customModelAdmin, RestApiUtil.toJsonAsString(aspect), 400);
// Try to create a model with an invalid aspect name (name is empty)
aspect.setName("");
post(aspectURL, customModelAdmin, RestApiUtil.toJsonAsString(aspect), 400);
// Try to create a model with an invalid aspect name (name contains '>')
aspect.setName("testType>name");
post(aspectURL, customModelAdmin, RestApiUtil.toJsonAsString(aspect), 400);
}
}
@Test
public void testCreateAspectsAndTypesWithProperties() throws Exception
{
String modelName = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
{
// Add aspect with property
String aspectName = "testAspect1" + System.currentTimeMillis();
CustomAspect aspect = new CustomAspect();
aspect.setName(aspectName);
String aspectPropName = "testAspect1Prop1" + System.currentTimeMillis();
CustomModelProperty aspectProp = new CustomModelProperty();
aspectProp.setName(aspectPropName);
aspectProp.setTitle("property title");
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(aspectProp);
aspect.setProperties(props);
// Create aspect as a Model Administrator
post("cmm/" + modelName + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 201);
// Retrieve the created aspect
HttpResponse response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspect.getName(), 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
compareCustomTypesAspects(aspect, returnedAspect, "prefixedName", "dataType", "indexTokenisationMode");
assertEquals(1, returnedAspect.getProperties().size());
CustomModelProperty customModelProperty = returnedAspect.getProperties().get(0);
assertEquals(aspectPropName, customModelProperty.getName());
assertEquals("property title", customModelProperty.getTitle());
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + aspectPropName, customModelProperty.getPrefixedName());
assertEquals("Default data type is 'd:text'.", "d:text", customModelProperty.getDataType());
// Test default indexing options
assertTrue(customModelProperty.isIndexed());
assertEquals(Facetable.UNSET, customModelProperty.getFacetable());
assertEquals(IndexTokenisationMode.TRUE, customModelProperty.getIndexTokenisationMode());
}
{
// Add type with properties
String typeName = "testType1" + System.currentTimeMillis();
CustomType type = new CustomType();
type.setName(typeName);
type.setDescription("test type1 Desc");
type.setTitle("test type1 title");
type.setParentName("cm:content");
String typePropName = "testType1Prop1" + System.currentTimeMillis();
CustomModelProperty typeProp = new CustomModelProperty();
typeProp.setName(typePropName);
typeProp.setDataType("int"); // data type without dictionary prefix
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(typeProp);
type.setProperties(props);
// Create type as a Model Administrator
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 400);
typeProp.setDataType("d:int");
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 201);
// Retrieve the created type
HttpResponse response = getSingle("cmm/" + modelName + "/types", customModelAdmin, type.getName(), 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
compareCustomTypesAspects(type, returnedType, "prefixedName", "indexTokenisationMode");
assertEquals("Shouldn't list the inherited properties from 'cm:content'.", 1, returnedType.getProperties().size());
CustomModelProperty customModelProperty = returnedType.getProperties().get(0);
assertEquals(typePropName, customModelProperty.getName());
assertEquals("d:int", customModelProperty.getDataType());
assertEquals(namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typePropName, customModelProperty.getPrefixedName());
// Test default indexing options
assertTrue(customModelProperty.isIndexed());
assertEquals(Facetable.UNSET, customModelProperty.getFacetable());
assertEquals(IndexTokenisationMode.TRUE, customModelProperty.getIndexTokenisationMode());
}
{
// Add more types with the same parent
// Test to make sure the inherited properties are excluded properly.
// As without parents property exclusion, we wont be able to
// create multiple types|aspects with the same parent.
String typeName2 = "testType2" + System.currentTimeMillis();
CustomType type2 = new CustomType();
type2.setName(typeName2);
type2.setDescription("test type2 Desc");
type2.setTitle("test type2 title");
type2.setParentName("cm:content");
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type2), 201);
String typeName3 = "testType3" + System.currentTimeMillis();
CustomType type3 = new CustomType();
type3.setName(typeName3);
type3.setDescription("test type3 Desc");
type3.setTitle("test type3 title");
type3.setParentName("cm:content");
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type3), 201);
}
{
// Retrieve the created model
HttpResponse response = getSingle("cmm", customModelAdmin, modelName, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertNull(returnedModel.getTypes());
assertNull(returnedModel.getAspects());
// Retrieve the created model with its types and aspects
response = getSingle("cmm", customModelAdmin, modelName + SELECT_ALL, 200);
returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertNotNull(returnedModel.getTypes());
assertEquals(3, returnedModel.getTypes().size());
assertNotNull(returnedModel.getAspects());
assertEquals(1, returnedModel.getAspects().size());
}
}
@Test
//SHA-679
public void testCustomModelTypesAspectsDependencies() throws Exception
{
String modelNameOne = "testModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelNameOne, namespacePair, ModelStatus.DRAFT, null, "Mark Moe");
// Add type
String typeBaseName = "testTypeBase" + System.currentTimeMillis();
final String typeBaseNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeBaseName;
createTypeAspect(CustomType.class, modelNameOne, typeBaseName, "test typeBase title", "test typeBase Desc", "cm:content");
// Activate the model
CustomModel modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
HttpResponse response = getSingle("cmm", customModelAdmin, modelNameOne, 200);
CustomModel returnedModel = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomModel.class);
assertEquals(ModelStatus.ACTIVE, returnedModel.getStatus());
// Add another type with 'typeBaseName' as its parent
String typeName2 = "testTypeChild" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelNameOne, typeName2, "test typeChild title", "test typeChild Desc", typeBaseNameWithPrefix);
Paging paging = getPaging(0, Integer.MAX_VALUE);
response = getAll("cmm/" + modelNameOne + "/types", customModelAdmin, paging, 200);
List<CustomType> returnedTypes = RestApiUtil.parseRestApiEntries(response.getJsonResponse(), CustomType.class);
assertEquals(2, returnedTypes.size());
// Create another model
String modelNameTwo = "testModelTwo" + System.currentTimeMillis();
Pair<String, String> modelTwoNamespacePair = getTestNamespaceUriPrefixPair();
createCustomModel(modelNameTwo, modelTwoNamespacePair, ModelStatus.DRAFT, null, "Admin");
// Add a type with 'typeBaseName' from the modelOne as its parent
String modelTwoTypeName = "testModelTwoChild" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelNameTwo, modelTwoTypeName, "test model two type child title", null, typeBaseNameWithPrefix);
// Try to deactivate modelOne
modelOneStatusPayload = new CustomModel();
modelOneStatusPayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 409); // ModelTwo depends on ModelOne
// Activate modelTwo
CustomModel modelTwoStatusPayload = new CustomModel();
modelTwoStatusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(modelTwoStatusPayload), SELECT_STATUS_QS, 200);
// Try to deactivate modelOne again. The dependent model is Active now, however, the result should be the same.
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 409); // ModelTwo depends on ModelOne
// Deactivate modelTwo
modelTwoStatusPayload = new CustomModel();
modelTwoStatusPayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelNameTwo, RestApiUtil.toJsonAsString(modelTwoStatusPayload), SELECT_STATUS_QS, 200);
// Delete the modelTwo's type as a Model Administrator
delete("cmm/" + modelNameTwo + "/types", customModelAdmin, modelTwoTypeName, 204);
// Try to deactivate modelOne again. There is no dependency
put("cmm", customModelAdmin, modelNameOne, RestApiUtil.toJsonAsString(modelOneStatusPayload), SELECT_STATUS_QS, 200);
}
@Test
public void testDeleteTypeAspect() throws Exception
{
final String modelName = "testDeleteTypeModel" + System.currentTimeMillis();
Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT, null, "Joe Bloggs");
// Add type
final String typeName = "testType" + System.currentTimeMillis();
final String typeNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + typeName;
CustomType type = createTypeAspect(CustomType.class, modelName, typeName, "test type title", "test type Desc", "cm:content");
// Add aspect
final String aspectName = "testAspect" + System.currentTimeMillis();
final String aspectNameWithPrefix = namespacePair.getSecond() + QName.NAMESPACE_PREFIX + aspectName;
CustomAspect aspect = createTypeAspect(CustomAspect.class, modelName, aspectName, null, null, null);
// Delete type
{
// Try to delete the model's type as a non Admin user
delete("cmm/" + modelName + "/types", nonAdminUserName, typeName, 403);
// Delete the model's type as a Model Administrator
delete("cmm/" + modelName + "/types", customModelAdmin, typeName, 204);
// Try to retrieve the deleted type
getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 404);
}
// Delete Aspect
{
// Try to delete the model's aspect as a non Admin user
delete("cmm/" + modelName + "/aspects", nonAdminUserName, aspectName, 403);
// Delete the model's aspect as a Model Administrator
delete("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 204);
// Try to retrieve the deleted aspect
getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 404);
}
// Create the type again
post("cmm/" + modelName + "/types", customModelAdmin, RestApiUtil.toJsonAsString(type), 201);
// Retrieve the created type
HttpResponse response = getSingle("cmm/" + modelName + "/types", customModelAdmin, type.getName(), 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
compareCustomTypesAspects(type, returnedType, "prefixedName");
// Create the aspect again
post("cmm/" + modelName + "/aspects", customModelAdmin, RestApiUtil.toJsonAsString(aspect), 201);
// Retrieve the created aspect
response = getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspect.getName(), 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
compareCustomTypesAspects(aspect, returnedAspect, "prefixedName");
// Update the Type by adding property
CustomType payload = new CustomType();
payload.setName(typeName);
String typePropName = "testType1Prop1" + System.currentTimeMillis();
CustomModelProperty typeProp = new CustomModelProperty();
typeProp.setName(typePropName);
typeProp.setTitle("property title");
typeProp.setDataType("d:int");
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(typeProp);
payload.setProperties(props);
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(payload), SELECT_PROPS_QS, 200);
// Activate the model
CustomModel statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.ACTIVE);
// Activate the model as a Model Administrator
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// Test for SHA-703
// Add another type with 'typeName' as its parent
final String childTypeName = "testChildType" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, childTypeName, "test child type title", null, typeNameWithPrefix);
// Add another aspect with 'aspectName' as its parent
final String childAspectName = "testChildAspect" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, childAspectName, "test child aspect title", null, aspectNameWithPrefix);
// Delete the model's type as a Model Administrator
delete("cmm/" + modelName + "/types", customModelAdmin, typeName, 409); // Cannot delete a type of an active model
// Delete the model's aspect as a Model Administrator
delete("cmm/" + modelName + "/aspects", customModelAdmin, childAspectName, 409); // Cannot delete an aspect of an active model
// Deactivate the model
statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.DRAFT);
// Deactivate the model as a Model Administrator
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// Delete type
{
// Try to delete the model's type (parent) as a Model Administrator
delete("cmm/" + modelName + "/types", customModelAdmin, typeName, 409); // conflict: childTypeName depends on typeName
// Delete the child type first
delete("cmm/" + modelName + "/types", customModelAdmin, childTypeName, 204);
// Try to retrieve the deleted child type
getSingle("cmm/" + modelName + "/types", customModelAdmin, childTypeName, 404);
// Now delete the parent type
delete("cmm/" + modelName + "/types", customModelAdmin, typeName, 204);
// Try to retrieve the deleted parent type
getSingle("cmm/" + modelName + "/types", customModelAdmin, typeName, 404);
}
// Delete Aspect
{
// Try to delete the model's aspect (parent) as a Model Administrator
delete("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 409); // conflict: childAspectName depends on aspectName
// Delete the child aspect first
delete("cmm/" + modelName + "/aspects", customModelAdmin, childAspectName, 204);
// Try to retrieve the deleted child aspect
getSingle("cmm/" + modelName + "/aspects", customModelAdmin, childAspectName, 404);
// Now delete the parent aspect
delete("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 204);
// Try to retrieve the deleted parent aspect
getSingle("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, 404);
}
}
@Test
public void testUpdateAspectsTypes() throws Exception
{
String modelName = "testModeEditAspectType" + System.currentTimeMillis();
final Pair<String, String> namespacePair = getTestNamespaceUriPrefixPair();
// Create the model as a Model Administrator
createCustomModel(modelName, namespacePair, ModelStatus.DRAFT);
// Test update aspect
{
// Create aspect
String aspectName = "testAspect" + System.currentTimeMillis();
createTypeAspect(CustomAspect.class, modelName, aspectName, "title", "desc", null);
// Update the aspect
CustomAspect aspectPayload = new CustomAspect();
aspectPayload.setDescription(null);
aspectPayload.setTitle("title modified");
aspectPayload.setParentName("cm:titled");
// Try to update the aspect as a non Admin user
put("cmm/" + modelName + "/aspects", nonAdminUserName, aspectName, RestApiUtil.toJsonAsString(aspectPayload), null, 403);
// Modify the name
aspectPayload.setName(aspectName + "Modified");
// Try to update the aspect as a Model Administrator
// Note: aspect/type name cannot be modified
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), null, 404);
aspectPayload.setName(aspectName);
// Update the aspect as a Model Administrator
HttpResponse response = put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), null, 200);
CustomAspect returnedAspect = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomAspect.class);
compareCustomTypesAspects(aspectPayload, returnedAspect, "prefixedName");
// Update the aspect with an invalid parent
aspectPayload.setParentName("cm:titled" + System.currentTimeMillis());
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), null, 409);
// Activate the model
CustomModel statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// Remove the aspect's parent
// Note: cannot update the parent of an ACTIVE type/aspect.
aspectPayload.setParentName(null);
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), null, 409);
statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// now update the aspect's parent - model is inactive
put("cmm/" + modelName + "/aspects", customModelAdmin, aspectName, RestApiUtil.toJsonAsString(aspectPayload), null, 200);
}
// Test update type
{
// Create type
String typeName = "testType" + System.currentTimeMillis();
createTypeAspect(CustomType.class, modelName, typeName, "title", "desc", "cm:content");
// Add property
CustomType addPropertyPayload = new CustomType();
addPropertyPayload.setName(typeName);
String typePropName = "testTypeProp1" + System.currentTimeMillis();
CustomModelProperty typeProp = new CustomModelProperty();
typeProp.setName(typePropName);
typeProp.setTitle("property title");
typeProp.setDataType("d:text");
List<CustomModelProperty> props = new ArrayList<>(1);
props.add(typeProp);
addPropertyPayload.setProperties(props);
// Create the property
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(addPropertyPayload), SELECT_PROPS_QS, 200);
// Update the type
CustomType typePayload = new CustomType();
typePayload.setDescription("desc modified");
typePayload.setTitle("title modified");
// Try to update the type as a non Admin user
put("cmm/" + modelName + "/types", nonAdminUserName, typeName, RestApiUtil.toJsonAsString(typePayload), null, 403);
// Modify the name
typePayload.setName(typeName + "Modified");
// Try to update the type as a Model Administrator
// Note: type/type name cannot be modified
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), null, 404);
typePayload.setName(typeName);
// Update the type as a Model Administrator
HttpResponse response = put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), null, 200);
CustomType returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
assertEquals(typePayload.getDescription(), returnedType.getDescription());
assertEquals(typePayload.getTitle(), returnedType.getTitle());
// Check that properties are unmodified
assertNotNull(returnedType.getProperties());
assertEquals(1, returnedType.getProperties().size());
assertEquals(typePropName, returnedType.getProperties().iterator().next().getName());
// Update the type with an invalid parent
typePayload.setParentName("cm:folder" + System.currentTimeMillis());
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), null, 409);
// Activate the model
CustomModel statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.ACTIVE);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// Remove the type's parent
// Note: cannot update the parent of an ACTIVE type/type.
typePayload.setParentName("cm:folder");
put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), null, 409);
statusPayload = new CustomModel();
statusPayload.setStatus(ModelStatus.DRAFT);
put("cmm", customModelAdmin, modelName, RestApiUtil.toJsonAsString(statusPayload), SELECT_STATUS_QS, 200);
// now update the type's parent - model is inactive
response = put("cmm/" + modelName + "/types", customModelAdmin, typeName, RestApiUtil.toJsonAsString(typePayload), null, 200);
returnedType = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), CustomType.class);
assertEquals(typePayload.getParentName(), returnedType.getParentName());
}
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.rest.api.tests.util;
import static org.junit.Assert.assertNotNull;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
/**
* A utility class for Rest API tests
*
* @author Jamal Kaabi-Mofrad
*/
public class RestApiUtil
{
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private RestApiUtil()
{
}
/**
* Parses the alfresco REST API response for a collection of entries.
* Basically, it looks for the {@code list} JSON object, then it uses
* {@literal Jackson} to convert the list's entries to their corresponding
* POJOs based on the given {@code clazz}.
*
* @param jsonObject the {@code JSONObject} derived from the response
* @param clazz the class which represents the JSON payload
* @return list of POJOs of the given {@code clazz} type
* @throws Exception
*/
public static <T> List<T> parseRestApiEntries(JSONObject jsonObject, Class<T> clazz) throws Exception
{
assertNotNull(jsonObject);
assertNotNull(clazz);
List<T> models = new ArrayList<>();
JSONObject jsonList = (JSONObject) jsonObject.get("list");
assertNotNull(jsonList);
JSONArray jsonEntries = (JSONArray) jsonList.get("entries");
assertNotNull(jsonEntries);
for (int i = 0; i < jsonEntries.size(); i++)
{
JSONObject jsonEntry = (JSONObject) jsonEntries.get(i);
T pojoModel = parseRestApiEntry(jsonEntry, clazz);
models.add(pojoModel);
}
return models;
}
/**
* Parses the alfresco REST API response for a single entry. Basically, it
* looks for the {@code entry} JSON object, then it uses {@literal Jackson}
* to convert it to its corresponding POJO based on the given {@code clazz}.
*
* @param jsonObject the {@code JSONObject} derived from the response
* @param clazz the class which represents the JSON payload
* @return the POJO of the given {@code clazz} type
* @throws Exception
*/
public static <T> T parseRestApiEntry(JSONObject jsonObject, Class<T> clazz) throws Exception
{
assertNotNull(jsonObject);
assertNotNull(clazz);
JSONObject entry = (JSONObject) jsonObject.get("entry");
T pojoModel = OBJECT_MAPPER.readValue(entry.toJSONString(), clazz);
assertNotNull(pojoModel);
return pojoModel;
}
/**
* Converts the POJO which represents the JSON payload into a JSON string
*/
public static String toJsonAsString(Object object) throws Exception
{
assertNotNull(object);
return OBJECT_MAPPER.writeValueAsString(object);
}
}

Binary file not shown.

Binary file not shown.