[rygel/wip/update-object] wip: Add UpdateObject action and an unfinished ItemUpdater.



commit e7141df46d9b374c45c3dede241780aef5d940c8
Author: Krzesimir Nowak <krnowak openismus com>
Date:   Thu Oct 11 16:29:51 2012 +0200

    wip: Add UpdateObject action and an unfinished ItemUpdater.

 src/librygel-server/filelist.am                  |    1 +
 src/librygel-server/rygel-content-directory.vala |   15 ++
 src/librygel-server/rygel-item-updater.vala      |  163 ++++++++++++++++++++++
 3 files changed, 179 insertions(+), 0 deletions(-)
---
diff --git a/src/librygel-server/filelist.am b/src/librygel-server/filelist.am
index c75b175..62046d6 100644
--- a/src/librygel-server/filelist.am
+++ b/src/librygel-server/filelist.am
@@ -47,6 +47,7 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
 	rygel-import-resource.vala \
 	rygel-item-creator.vala \
 	rygel-item-destroyer.vala \
+	rygel-item-updater.vala \
 	rygel-item-removal-queue.vala \
 	rygel-media-query-action.vala \
 	rygel-media-receiver-registrar.vala \
diff --git a/src/librygel-server/rygel-content-directory.vala b/src/librygel-server/rygel-content-directory.vala
index e68b710..7fa453f 100644
--- a/src/librygel-server/rygel-content-directory.vala
+++ b/src/librygel-server/rygel-content-directory.vala
@@ -31,12 +31,18 @@ using Gee;
  */
 internal errordomain Rygel.ContentDirectoryError {
     NO_SUCH_OBJECT = 701,
+    INVALID_CURRENT_TAG_VALUE = 702,
+    INVALID_NEW_TAG_VALUE = 703,
+    REQUIRED_TAG = 704,
+    READ_ONLY_TAG = 705,
+    PARAMETER_MISMATCH = 706,
     INVALID_SORT_CRITERIA = 709,
     RESTRICTED_OBJECT = 711,
     BAD_METADATA = 712,
     RESTRICTED_PARENT = 713,
     NO_SUCH_DESTINATION_RESOURCE = 718,
     CANT_PROCESS = 720,
+    OUTDATED_OBJECT_METADATA = 728,
     INVALID_ARGS = 402
 }
 
@@ -96,6 +102,7 @@ internal class Rygel.ContentDirectory: Service {
         this.action_invoked["Search"].connect (this.search_cb);
         this.action_invoked["CreateObject"].connect (this.create_object_cb);
         this.action_invoked["DestroyObject"].connect (this.destroy_object_cb);
+        this.action_invoked["UpdateObject"].connect (this.update_object_cb);
         this.action_invoked["ImportResource"].connect (this.import_resource_cb);
         this.action_invoked["GetTransferProgress"].connect (
                                         this.get_transfer_progress_cb);
@@ -169,6 +176,14 @@ internal class Rygel.ContentDirectory: Service {
         destroyer.run.begin ();
     }
 
+    /* UpdateObject action implementation */
+    private void update_object_cb (Service       content_dir,
+                                   ServiceAction action) {
+        var updater = new ItemUpdater (this, action);
+
+        updater.run.begin ();
+    }
+
     /* ImportResource action implementation */
     private void import_resource_cb (Service       content_dir,
                                      ServiceAction action) {
diff --git a/src/librygel-server/rygel-item-updater.vala b/src/librygel-server/rygel-item-updater.vala
new file mode 100644
index 0000000..37098a9
--- /dev/null
+++ b/src/librygel-server/rygel-item-updater.vala
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * Author: Krzesimir Nowak <krnowak openismus com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using GUPnP;
+using Gee;
+
+/**
+ * UpdateObject action implementation.
+ */
+internal class Rygel.ItemUpdater: GLib.Object, Rygel.StateMachine {
+    private string object_id;
+    private string current_tag_value;
+    private string new_tag_value;
+
+    private ContentDirectory content_dir;
+    private ServiceAction action;
+
+    public Cancellable cancellable { get; set; }
+
+    public ItemUpdater (ContentDirectory    content_dir,
+                        owned ServiceAction action) {
+        this.content_dir = content_dir;
+        this.cancellable = content_dir.cancellable;
+        this.action = (owned) action;
+    }
+
+    public async void run () {
+        try {
+            this.action.get ("ObjectID", typeof (string), out this.object_id);
+            this.action.get ("CurrentTagValue",
+                             typeof (string),
+                             out this.current_tag_value);
+            this.action.get ("NewTagValue",
+                             typeof (string),
+                             out this.new_tag_value);
+            if (this.object_id == null) {
+                // Sorry we can't do anything without the ID
+                throw new ContentDirectoryError.NO_SUCH_OBJECT
+                                        (_("No such object"));
+            }
+            // I have no idea what to throw here.
+            // For now I just treat it as empty strings.
+            if (this.current_tag_value == null) {
+                this.current_tag_value = "";
+            }
+            if (this.new_tag_value == null) {
+                this.new_tag_value = "";
+            }
+
+            yield this.update_object ();
+
+            this.action.return ();
+
+            debug (_("Successfully destroyed object '%s'"), this.object_id);
+        } catch (Error error) {
+            if (error is ContentDirectoryError) {
+                this.action.return_error (error.code, error.message);
+            } else {
+                this.action.return_error (701, error.message);
+            }
+
+            warning (_("Failed to update object '%s': %s"),
+                     this.object_id,
+                     error.message);
+        }
+
+        this.completed ();
+    }
+
+    private static LinkedList<string> csv_split (string tag_values) {
+        var list = new LinkedList<string> ();
+        /*
+        var escape = false;
+        var token_start = 0;
+        var token_length = 0;
+        */
+
+        /* TODO: Find out how to iterate over chars in string.
+        foreach (var c in tag_values) {
+            if (escape) {
+                escape = false;
+            } else {
+                switch (c) {
+                case '\\':
+                    escape = true;
+                    break;
+
+                case ',':
+                    list.add (tag_values.substring (token_start, token_length));
+                    token_start += token_length + 1;
+                    token_length = 0;
+                    break;
+                }
+            }
+            ++token_length;
+        }
+        */
+
+        return list;
+    }
+
+    private async void update_object () throws Error {
+        var media_object = yield this.fetch_object ();
+        var current_list = csv_split (this.current_tag_value);
+        var new_list = csv_split (this.new_tag_value);
+
+        if (current_list.size != new_list.size) {
+            throw new ContentDirectoryError.PARAMETER_MISMATCH
+                (_("CurrentTagValue should have the same number of elements as " +
+                   "NewTagValue (%s vs %s)."),
+                 current_list.size,
+                 new_list.size);
+        }
+        /* Just to avoid some unused warning. */
+        if (media_object == null) {
+            return;
+        }
+    }
+
+    private async MediaObject fetch_object () throws Error {
+        var media_object = yield this.content_dir.root_container.find_object
+                                        (this.object_id, this.cancellable);
+
+        if (media_object == null) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT
+                                        (_("No such object"));
+        } else if (!(OCMFlags.CHANGE_METADATA in media_object.ocm_flags)) {
+            var msg = _("Metadata modification of object %s not allowed");
+
+            throw new ContentDirectoryError.RESTRICTED_OBJECT (msg,
+                                                               media_object.id);
+        } else if (media_object.parent.restricted) {
+            var msg = _("Metadata modification of object %s being a child " +
+                        "of restricted object %s not allowed");
+
+            throw new ContentDirectoryError.RESTRICTED_PARENT
+                                        (msg,
+                                         media_object.id,
+                                         media_object.parent.id);
+        }
+
+        return media_object;
+    }
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]