+
+ return if $done->{$key}; # avoid duplicates
+
+ $done->{$key} = 1;
+
+ my $phash = $format->{$key};
+
+ return if !$phash; # should not happen
+
+ return if $phash->{alias};
+
+ &$format_key_value($key, $phash);
+
+ };
+
+ &$cond_add_key($default_key) if defined($default_key);
+
+ # add required keys first
+ foreach my $key (sort keys %$format) {
+ my $phash = $format->{$key};
+ &$cond_add_key($key) if $phash && !$phash->{optional};
+ }
+
+ # add the rest
+ foreach my $key (sort keys %$format) {
+ &$cond_add_key($key);
+ }
+
+ foreach my $keyAlias (sort keys %$keyAliasProps) {
+ &$add_option_string("<$keyAlias>=<$keyAliasProps->{$keyAlias }>", 1);
+ }
+
+ return $res;
+}
+
+sub print_property_string {
+ my ($data, $format, $skip, $path) = @_;
+
+ if (ref($format) ne 'HASH') {
+ my $schema = get_format($format);
+ die "not a valid format: $format\n" if !$schema;
+ $format = $schema;
+ }
+
+ my $errors = {};
+ check_object($path, $format, $data, undef, $errors);
+ if (scalar(%$errors)) {
+ raise "format error", errors => $errors;
+ }
+
+ my ($default_key, $keyAliasProps) = &$find_schema_default_key($format);
+
+ my $res = '';
+ my $add_sep = 0;
+
+ my $add_option_string = sub {
+ my ($text) = @_;
+
+ $res .= ',' if $add_sep;
+ $res .= $text;
+ $add_sep = 1;
+ };
+
+ my $format_value = sub {
+ my ($key, $value, $format) = @_;
+
+ if (defined($format) && ($format eq 'disk-size')) {
+ return format_size($value);