diff --git a/app/assets/javascripts/application/collections.coffee b/app/assets/javascripts/application/collections.coffee
index 21be34e58037bc06cec0d93a6a8c0c6842872552..682a2f9738788679eeba61af6a293331f381e937 100644
--- a/app/assets/javascripts/application/collections.coffee
+++ b/app/assets/javascripts/application/collections.coffee
@@ -1,13 +1,13 @@
 $ ->
+  # create collection popover
   $('#create_collection_popover').popover
     html: true
     content: ->
       $('#create_collection_popover_content').html()
     title: ->
       $('#create_collection_popover_title').html()
-  return
 
-$ ->
+  # add learning object to collection
   $(document).on 'click', 'input[class=collection-element]', ->
     url = '/collections/' + encodeURIComponent($(this).data('cid')) + '/learning_object/' + encodeURIComponent($(this).data('loid'))
     if this.checked
@@ -16,12 +16,88 @@ $ ->
     else
       $.ajax {method: "DELETE", url: url }, (d) ->
         d
-  return
 
-$ ->
+  # change collection privacy
   $(document).on 'click', 'input[name=privacy]', ->
     url = '/collections/' + encodeURIComponent($(this).data('cid')) + '/change_privacy'
     value = $('input[name=privacy]:checked').val()
     $.post url, {'privacy':value}, (d) ->
       d
+
+  $(document).on 'open_collections_modal', (evt, params) ->
+    url = '/collections/' + encodeURIComponent(params) + '/list'
+    $.get url, (d) ->
+      $('#collections-modal').remove()
+      $('body').append d
+      $('#collections-modal').modal('show')
+      return
   return
+
+# manipulate collections in show page
+$ ->
+  $(document).on 'ready page:load', ->
+    if $('.collection-show-page').val() != undefined
+      # array with selected collections ids
+      selected_collections = []
+      collection = $('.collection-show-page').data('cid')
+
+      # add selectors
+      $('.learning-object-vertical').each (e) ->
+        loid = $(this).data('loid')
+        $('.learning-object-thumbnail', this).append '<input class="collection-selector" type="checkbox" value="' + loid + '"></input>'
+        return
+
+      # add/remove collection to array when click checkbox
+      $(document).on 'click', '.collection-selector', ->
+        if this.checked
+          if selected_collections.indexOf(this.value) < 0
+            selected_collections.push this.value
+            $(document).trigger('check_selected_collection');
+          return
+        else
+          index = selected_collections.indexOf(this.value)
+          if !!(~index)
+            selected_collections.splice(index, 1)
+            $(document).trigger('check_selected_collection');
+          return
+
+      # clear selected collections
+      $(document).on 'clear_collections', ->
+        selected_collections = []
+        $('.collection-selector').attr('checked', false);
+        $(document).trigger('check_selected_collection')
+
+      $(document).on 'click', '.collection-show-select-nav .navbar-brand', ->
+        $(document).trigger('clear_collections')
+
+      # manipulation buttons
+      $(document).on 'click', '.collection-button', ->
+        switch $(this).data('action')
+          when 'download' then
+          when 'copy' then $(document).trigger('open_collections_modal', [collection])
+          when 'move' then
+          when 'remove' then
+
+      # update interface when add/remove a collection
+      $(document).on 'check_selected_collection', (e) ->
+        length = selected_collections.length
+        if length == 0
+          return $('.collection-show-select-nav').slideUp('slow')
+        else if (length == 1)
+          html = "1 objeto selecionado"
+        else
+          html = length + " objetos selecionados"
+        $('.collection-show-select-nav .navbar-brand').html html
+        $('.collection-show-select-nav').slideDown('slow')
+
+      $(document).on 'submit', '#collections-modal-form', (evt) ->
+        evt.preventDefault()
+        url = '/collections/' + encodeURIComponent(collection) + '/copy'
+        collections = $(this).serializeArray()
+        $.ajax {method: "POST", url: url, data: {col: collections} }, (d) ->
+          console.log d
+          return
+        console.log collections
+        $('#collections-modal').modal('close')
+        return
+      return
diff --git a/app/assets/stylesheets/application/collections.scss b/app/assets/stylesheets/application/collections.scss
index 3a380078b0abaf7e7d10247258caa39bba4298d1..50eb4a46f19e5882ac04aee955872cd848971aa1 100644
--- a/app/assets/stylesheets/application/collections.scss
+++ b/app/assets/stylesheets/application/collections.scss
@@ -10,3 +10,9 @@ ul.collection-header {
   margin-top: 20px;
   margin-right: 30px;
 }
+
+.collection-show-select-nav {
+  .navbar-brand {
+    color: #FFF !important;
+  }
+}
diff --git a/app/assets/stylesheets/application/learning_objects.scss b/app/assets/stylesheets/application/learning_objects.scss
index 3d79699dbb96f38830a595b39e87dde7a1c13e34..2089a8e3504cece3dc1b922f0bc6ef8431260a06 100644
--- a/app/assets/stylesheets/application/learning_objects.scss
+++ b/app/assets/stylesheets/application/learning_objects.scss
@@ -85,6 +85,14 @@ $checked_icon: 'icons/checked.png';
     .learning-object-actions {
       bottom: 20px !important;
     }
+
+    .collection-selector {
+      position: absolute;
+      left: 10px;
+      top: 6px;
+      width: 28px;
+      height: 28px;
+    }
   }
 
 }
diff --git a/app/builders/attribute_builder.rb b/app/builders/attribute_builder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6cfa32b7e733a8e153e4d9cf1ad05ebc8dffb9e4
--- /dev/null
+++ b/app/builders/attribute_builder.rb
@@ -0,0 +1,37 @@
+class AttributeBuilder < Builder
+  extend RepositoriesProxy
+
+  ##
+  # receive a list of ids and return a list of attributes
+  #
+  def self.build(attributes = [])
+    array = []
+    attributes = [attributes] if attributes.class == String
+    attributes.each do |attributes|
+      unless attribute['@rid'].blank?
+        o = Rails.cache.fetch(cache_key(attribute['@rid'], attribute['last_modified'])) unless attribute['last_modified'].blank?
+        o = attribute_repository.find attribute['@rid'] if o.nil?
+        array << o
+      end
+    end
+    array
+  end
+
+  def self.build_from_orientdb(args = {})
+    attribute = nil
+
+    unless args.nil?
+      # cache object when build
+      attribute = Rails.cache.fetch(cache_key(args['@rid'], args['last_modified']), expires_in: 12.hours) do
+        Attribute.new(
+            id: args['@rid'],
+            key: args['key'],
+            value: args['value']
+        )
+      end
+    end
+
+    attribute
+  end
+
+end
diff --git a/app/builders/builder.rb b/app/builders/builder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..00973be93271e30449ed922505f78ba80a388da8
--- /dev/null
+++ b/app/builders/builder.rb
@@ -0,0 +1,9 @@
+class Builder
+
+  protected
+
+  def self.cache_key(rid, last_modified)
+    rid + '/' + last_modified
+  end
+
+end
\ No newline at end of file
diff --git a/app/builders/collection_builder.rb b/app/builders/collection_builder.rb
index 7726d5ae2469b26ddea1719c8ad94fd2cd24a0b2..35e043d90fb4400048fb8078eb71e22f142f0c7b 100644
--- a/app/builders/collection_builder.rb
+++ b/app/builders/collection_builder.rb
@@ -1,4 +1,4 @@
-class CollectionBuilder
+class CollectionBuilder < Builder
   extend RepositoriesProxy
 
   ##
@@ -42,10 +42,6 @@ class CollectionBuilder
     lo
   end
 
-  def self.cache_key(rid, last_modified)
-    rid + '/' + last_modified
-  end
-
   def self.map_rid_to_object(ids)
     return {'rid' => ids} if ids.class == String
 
diff --git a/app/builders/institution_builder.rb b/app/builders/institution_builder.rb
index df639251ad92ffe84ebe17a4395825ca692b3b39..2d1fa5a19a235559d133750307a499f85cdd1c21 100644
--- a/app/builders/institution_builder.rb
+++ b/app/builders/institution_builder.rb
@@ -1,4 +1,4 @@
-class InstitutionBuilder
+class InstitutionBuilder < Builder
   extend RepositoriesProxy
 
   ##
@@ -40,7 +40,4 @@ class InstitutionBuilder
     institution
   end
 
-  def self.cache_key(rid, last_modified)
-    rid + '/' + last_modified
-  end
 end
diff --git a/app/builders/learning_object_builder.rb b/app/builders/learning_object_builder.rb
index 513b4fa0fbd4afa4aa8774a0c2a861a6c1c54329..f5619b41f1594b714d53fb26f5eedf8497f694d9 100644
--- a/app/builders/learning_object_builder.rb
+++ b/app/builders/learning_object_builder.rb
@@ -1,4 +1,4 @@
-class LearningObjectBuilder
+class LearningObjectBuilder < Builder
   extend RepositoriesProxy
 
   ##
@@ -51,7 +51,4 @@ class LearningObjectBuilder
     lo
   end
 
-  def self.cache_key(rid, last_modified)
-    rid + '/' + last_modified
-  end
 end
diff --git a/app/builders/subject_builder.rb b/app/builders/subject_builder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b5fd7a1e328efde3bf064e26f5ae7794701bb868
--- /dev/null
+++ b/app/builders/subject_builder.rb
@@ -0,0 +1,42 @@
+class SubjectBuilder < Builder
+  extend RepositoriesProxy
+
+  ##
+  # receive a list of ids and return a list of subjects
+  #
+  # Example:
+  #   subject = SubjectBuilder.build '#15:135'
+  #   subjects = SubjectBuilder.build [{'@rid' => '#15:135'}, {'@rid' => '#15:140'}, {'@rid' => '#15:136'}]
+  #   subjects = SubjectBuilder.build [{'@rid' => '#15:135', 'last_modified' => '2015-30-10 15:44:12'}, {'@rid' => '#15:140'}, {'@rid' => '#15:136'}]
+  def self.build(subjects = [])
+    array = []
+    subjects = [subjects] if subjects.class == String
+    subjects.each do |subject|
+      unless subject['@rid'].blank?
+        o = Rails.cache.fetch(cache_key(subject['@rid'], subject['last_modified'])) unless subject['last_modified'].blank?
+        o = subject_repository.find subject['@rid'] if o.nil?
+        array << o
+      end
+    end
+    array
+  end
+
+  def self.build_from_orientdb(args = {})
+    subject = nil
+
+    unless args.nil?
+      # cache object when build
+      subject = Rails.cache.fetch(cache_key(args['@rid'], args['last_modified']), expires_in: 12.hours) do
+        Subject.new(
+            id: args['@rid'],
+            name: args['name'],
+            created_at: args['name'],
+            last_modified: args['name']
+        )
+      end
+    end
+
+    subject
+  end
+
+end
diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb
index 1c4a9bd6951f4a2a7ed83fca12e723cc742a66e7..d36cf9dcfb3a829302a4772f96d0008a1479c6f6 100644
--- a/app/controllers/collections_controller.rb
+++ b/app/controllers/collections_controller.rb
@@ -1,12 +1,12 @@
 class CollectionsController < ApplicationController
-  before_action :set_collection, only: [:show, :update, :destroy, :like, :add_learning_object, :remove_learning_object, :change_privacy]
-  before_action :authenticate_user!, only: [:update, :destroy, :like, :add_learning_object, :remove_learning_object, :change_privacy]
+  before_action :set_collection, only: [:show, :update, :destroy, :like, :list, :add_learning_object, :remove_learning_object, :move_learning_objects, :copy_learning_objects, :change_privacy]
+  before_action :authenticate_user!, only: [:update, :destroy, :like, :list, :add_learning_object, :remove_learning_object, :move_learning_objects, :copy_learning_objects, :change_privacy]
+  before_action :set_manipulation_params, only: [:move_learning_objects, :copy_learning_objects]
 
   # GET /collections
   # GET /collections.json
   def index
     respond_to do |format|
-
       # for HTML page, returns institutional collections
       format.html do
         context = Collections::InstitutionsContext.new(institution_repository.all)
@@ -74,6 +74,14 @@ class CollectionsController < ApplicationController
     end
   end
 
+  def list
+    @learning_object = learning_object_repository.find params[:learning_object_id] unless params[:learning_object_id].blank?
+
+    @collections = collection_repository.all Collections::UserContext.new(current_user)
+
+    render layout: false
+  end
+
   # POST /collections/1/learning_object/43
   def add_learning_object
     learning_object = learning_object_repository.find params[:learning_object_id]
@@ -95,6 +103,30 @@ class CollectionsController < ApplicationController
     end
   end
 
+  def copy_learning_objects
+    response = learning_objects_to_collection(@learning_objects, @target_collection)
+
+    if request.xhr?
+      render json: {status: response}
+    end
+  end
+
+  def move_learning_objects
+    response = learning_objects_to_collection(@learning_objects, @target_collection)
+
+    if response
+      @learning_objects.each do |learning_object|
+        @collection.remove learning_object
+      end
+
+      response = collection_repository.save_learning_objects(@target_collection)
+    end
+
+    if request.xhr?
+      render json: {status: response}
+    end
+  end
+
   # change collection privacy
   def change_privacy
     collection_repository.change_privacy(@collection, params[:privacy])
@@ -109,6 +141,16 @@ class CollectionsController < ApplicationController
   def authorize_create_collection!
   end
 
+  def learning_objects_to_collection(learning_objects, collection)
+    if collection.owner?
+      learning_objects.each do |learning_object|
+        collection.add learning_object
+      end
+
+      return collection_repository.save_learning_objects(@target_collection)
+    end
+  end
+
   def check_collection_privacy!(collection)
     if collection.privacy == "private"
       redirect_to :root, notice: 'Está é uma coleção privada.' unless collection.owner?(current_user)
@@ -119,6 +161,14 @@ class CollectionsController < ApplicationController
     @collection = collection_repository.find params[:id]
   end
 
+  def set_manipulation_params
+    p "AQUI"
+    p JSON.stringify(params)
+    @target_collection = collection_repository.find params[:collection_id] unless params[:collection_id].empty?
+
+    @learning_objects = params[:learning_objects].map{|id| learning_object_repository.find id || false} unless params[:learning_objects].empty?
+  end
+
   # Never trust parameters from the scary internet, only allow the white list through.
   def collection_params
     params.require(:collection).permit(:name, :description, :owner,learning_objects: [])
diff --git a/app/models/subject.rb b/app/models/subject.rb
index b728700ecac33a6ea1631ccc1e1ee3ebfa5835d9..8e3b4050e92395eb9938dfa588c18aee8a209d62 100644
--- a/app/models/subject.rb
+++ b/app/models/subject.rb
@@ -2,7 +2,7 @@ class Subject
   include ActiveModel::Model
   include RepositoriesProxy
 
-  attr_accessor :id, :description, :highlights, :name, 
+  attr_accessor :id, :highlights, :name,
                 :created_at, :last_modified,
                 :learning_objects, :subtopics, :supertopics
 
diff --git a/app/repositories/active_record/carousel_repository.rb b/app/repositories/active_record/carousel_repository.rb
index cb77877a8cde65fb8e7aacbefae0ef33a29e0a27..6057c41184caf7771e750f067c9142bce358384c 100644
--- a/app/repositories/active_record/carousel_repository.rb
+++ b/app/repositories/active_record/carousel_repository.rb
@@ -14,7 +14,6 @@ class ActiveRecord::CarouselRepository
     Carousel.send(method_name, *arguments, &block)
   end
 
-
   def respond_to?(method_name, include_private = false)
     Carousel.respond_to?(method_name) || super
   end
diff --git a/app/repositories/orient_db/attribute_repository.rb b/app/repositories/orient_db/attribute_repository.rb
index b0f5de18c9c01dcb27745b0bfdce86ba4a0d72ca..72c0628664cee854cf547404cade98e9da6f97a9 100644
--- a/app/repositories/orient_db/attribute_repository.rb
+++ b/app/repositories/orient_db/attribute_repository.rb
@@ -1,9 +1,9 @@
 module OrientDb
   class AttributeRepository < Base
-    
+
     def find_by_key_and_value(key, value)
       # Escape double quotes for OrientDB
-      v = value.gsub('"','\\"')
+      v = value.gsub('"', '\\"')
       result = connection.query("SELECT EXPAND(rid) FROM INDEX:attr_unique WHERE key = [\"#{key}\", \"#{v}\"]")
       build_object(result.first)
     end
@@ -13,23 +13,7 @@ module OrientDb
     end
 
     def build_object(args={})
-      attribute = nil
-      unless args.nil?
-        attribute = Attribute.new(:id => args["@rid"])
-        args.each do |var, val|
-          var_name = "@"+var
-          if attribute.respond_to?(var)
-            attribute.instance_variable_set(var_name, val)
-          end
-        end
-      end
-      attribute
-    end
-    
-    private
-
-    def odb_class
-        "Attribute"
+      AttributeBuilder.build_from_orientdb args
     end
 
   end
diff --git a/app/repositories/orient_db/base.rb b/app/repositories/orient_db/base.rb
index 65c4f052a1826eb341098f4918be628b42098d87..394b8857567e0a0a087f01914908b96fc914bd3e 100644
--- a/app/repositories/orient_db/base.rb
+++ b/app/repositories/orient_db/base.rb
@@ -78,7 +78,8 @@ class OrientDb::Base
   end
 
   def odb_class
-    raise NoMethodError, "You must implement this method"
+    fullname = self.class.to_s.split('Repository').first
+    fullname.split('::').last.to_s
   end
 
 end
diff --git a/app/repositories/orient_db/collection_repository.rb b/app/repositories/orient_db/collection_repository.rb
index 752740b081f02f8c2c69d4de02b22ccacee7a23e..67836427b5b9ced2367491455f3287bfdf326605 100644
--- a/app/repositories/orient_db/collection_repository.rb
+++ b/app/repositories/orient_db/collection_repository.rb
@@ -131,9 +131,5 @@ module OrientDb
       (owner.class == User) ? owner.rid : owner.id
     end
 
-    def odb_class
-      'Collection'
-    end
-
   end
 end
diff --git a/app/repositories/orient_db/complaint_repository.rb b/app/repositories/orient_db/complaint_repository.rb
index 6861675192c531c4c27d9f67e381d172afbe6a7c..f0419fe6d8ecc5347dadf84ae020c503698e66d4 100644
--- a/app/repositories/orient_db/complaint_repository.rb
+++ b/app/repositories/orient_db/complaint_repository.rb
@@ -3,48 +3,41 @@ module OrientDb
     include OrientDb::Methods::EdgeMethods
     include RepositoriesProxy
 
-      def report(complaint)
-        if edge_exists?(odb_class, complaint.user.rid, complaint.object)
-          false
-        else
-          connection.command "CREATE EDGE Complaint FROM #{complaint.user.rid} TO #{complaint.object} SET message = '#{complaint.message}', description = '#{complaint.description}'"
-        end
-      end
-
-      def destroy(user_rid,object_rid)
-        if !edge_exists?(odb_class, user_rid, object_rid)
-          raise "The object has not been reported by you yet."
-        end
-
-        connection.command "DELETE EDGE Complaint FROM #{user_rid} TO #{object_rid}"
+    def report(complaint)
+      if edge_exists?(odb_class, complaint.user.rid, complaint.object)
+        false
+      else
+        connection.command "CREATE EDGE Complaint FROM #{complaint.user.rid} TO #{complaint.object} SET message = '#{complaint.message}', description = '#{complaint.description}'"
       end
+    end
 
-      def build_object(args={})
-        Complaint.new(args)
+    def destroy(user_rid, object_rid)
+      if !edge_exists?(odb_class, user_rid, object_rid)
+        raise "The object has not been reported by you yet."
       end
 
-      def get_complaints
-        result = connection.command "SELECT FROM Complaint"
-        build_complaint result
-      end
+      connection.command "DELETE EDGE Complaint FROM #{user_rid} TO #{object_rid}"
+    end
 
+    def build_object(args={})
+      Complaint.new(args)
+    end
 
-      def build_complaint(args)
-        complaint = Array.new
-        for i in 0..args["result"].length-1
-          unless args.nil?
-            complaint[i] = Complaint.new(:user => args["result"][i]["out"], :object => args["result"][i]["in"], :message => args["result"][i]["message"], :description =>args["result"][i]["description"])
-          end
-        end
-        complaint
-      end
+    def get_complaints
+      result = connection.command "SELECT FROM Complaint"
+      build_complaint result
+    end
 
 
-      protected
-
-      def odb_class
-        "Complaint"
+    def build_complaint(args)
+      complaint = Array.new
+      for i in 0..args["result"].length-1
+        unless args.nil?
+          complaint[i] = Complaint.new(:user => args["result"][i]["out"], :object => args["result"][i]["in"], :message => args["result"][i]["message"], :description => args["result"][i]["description"])
+        end
       end
+      complaint
+    end
 
   end
 end
diff --git a/app/repositories/orient_db/institution_repository.rb b/app/repositories/orient_db/institution_repository.rb
index 56d841fdb58635a0306bde84e60273aa138b0172..6c03fa646f1c367ef9394799429f77dbe51681e1 100644
--- a/app/repositories/orient_db/institution_repository.rb
+++ b/app/repositories/orient_db/institution_repository.rb
@@ -51,11 +51,5 @@ module OrientDb
       InstitutionBuilder.build_from_orientdb args
     end
 
-    private
-
-    def odb_class
-      "Institution"
-    end
-
   end
 end
diff --git a/app/repositories/orient_db/learning_object/relation.rb b/app/repositories/orient_db/learning_object/relation.rb
index 066eabf834914a88e0189307a93bc1020f168887..f56115f8376769293f9a8cda26c5d00be323b3f6 100644
--- a/app/repositories/orient_db/learning_object/relation.rb
+++ b/app/repositories/orient_db/learning_object/relation.rb
@@ -1,6 +1,6 @@
 module OrientDb
   module LearningObject
-    class Relation
+    class Relation < OrientDb::Relation
       include OrientDb::Methods::EdgeMethods
 
       def initialize(learning_object)
diff --git a/app/repositories/orient_db/learning_object/relations_chain.rb b/app/repositories/orient_db/learning_object/relations_chain.rb
index 03c2b217e6efbe1dcef685807f7fcab071e14f00..c5aa198dd9c3e343ebbe31075416f26649282c02 100644
--- a/app/repositories/orient_db/learning_object/relations_chain.rb
+++ b/app/repositories/orient_db/learning_object/relations_chain.rb
@@ -1,19 +1,15 @@
 module OrientDb
   module LearningObject
-    class RelationsChain
+    class RelationsChain < OrientDb::RelationChain
 
-      def initialize(learning_object)
-        @relations = [
-            OrientDb::LearningObject::SubjectsRelations.new(learning_object),
-            OrientDb::LearningObject::AttributesRelations.new(learning_object),
-            OrientDb::LearningObject::PublisherRelation.new(learning_object)
+      def relations
+        [
+            OrientDb::LearningObject::SubjectsRelations.new(object),
+            OrientDb::LearningObject::AttributesRelations.new(object),
+            OrientDb::LearningObject::PublisherRelation.new(object)
         ]
       end
 
-      def create
-        @relations.each { |relation| relation.create }
-      end
-
     end
   end
 end
\ No newline at end of file
diff --git a/app/repositories/orient_db/learning_object_repository.rb b/app/repositories/orient_db/learning_object_repository.rb
index 293f8686437c606ee902433d85cee2f406113438..b4445e07783fdcfc686943919a612e7164aa9ae9 100644
--- a/app/repositories/orient_db/learning_object_repository.rb
+++ b/app/repositories/orient_db/learning_object_repository.rb
@@ -92,33 +92,11 @@ module OrientDb
     #   FULLTEXT ENGINE LUCENE
     #   METADATA {"analyzer":"org.apache.lucene.analysis.br.BrazilianAnalyzer"}
     def search(params)
-      # mount cache_key with params
-      valid_params = %w(query order subject type school_level year)
-      cache_key = "search_result/"
-      valid_params.each do |param|
-        if params[param].class == Array
-          cache_key += params[param].join('-')
-        else
-          cache_key += params[param].to_s
-        end
-        cache_key += '/' unless (param == valid_params.last)
-      end
+      cache_key = build_search_cache_key params
 
       # get results in cache or search
       Rails.cache.fetch(cache_key, expires_in: 10.minutes) do
-        qry = params[:query]
-        order = order_by(params[:order])
-
-        query = "SELECT FROM LearningObject WHERE [name, description, author] LUCENE '#{qry}'"
-        query += " AND out('IsAbout') CONTAINS (name in ['" + params[:subject].join("','") + "'])" unless params[:subject].blank?
-        unless params[:school_level].blank?
-          params[:school_level] << 'Ensino Fundamental Inicial' << 'Ensino Fundamental Final' if params[:school_level].include? 'Ensino Fundamental'
-          query += " AND out('IsAbout') CONTAINS (name in ['" + params[:school_level].join("','") + "'])"
-        end
-        query = "SELECT * FROM (" + query + ") WHERE " + fetch_types(params[:type]) unless params[:type].blank?
-        query = "SELECT * FROM (" + query + ") WHERE " + fetch_year(params[:year]) unless params[:year].blank?
-        query = "SELECT * FROM (" + query + ") ORDER BY #{order}"
-        query = "SELECT @rid.asString(), last_modified FROM (" + query + ")"
+        query = build_search_query params
         connection.query query, limit: 10000
       end
     end
@@ -180,8 +158,35 @@ module OrientDb
       ['thumbnail', 'score']
     end
 
-    def odb_class
-      "LearningObject"
+    def build_search_query(params={})
+      query = "SELECT FROM LearningObject WHERE [name, description, author] LUCENE '#{params[:query]}'"
+      query += " AND out('IsAbout') CONTAINS (name in ['" + params[:subject].join("','") + "'])" unless params[:subject].blank?
+      unless params[:school_level].blank?
+        params[:school_level] << 'Ensino Fundamental Inicial' << 'Ensino Fundamental Final' if params[:school_level].include? 'Ensino Fundamental'
+        query += " AND out('IsAbout') CONTAINS (name in ['" + params[:school_level].join("','") + "'])"
+      end
+      query = "SELECT * FROM (" + query + ") WHERE " + fetch_types(params[:type]) unless params[:type].blank?
+      query = "SELECT * FROM (" + query + ") WHERE " + fetch_year(params[:year]) unless params[:year].blank?
+      query = "SELECT * FROM (" + query + ") ORDER BY #{order_by(params[:order])}"
+      query = "SELECT @rid.asString(), last_modified FROM (" + query + ")"
+      query
+    end
+
+    def search_params
+      %w(query order subject type school_level year)
+    end
+
+    def build_search_cache_key(params={})
+      cache_key = "search_result/"
+      search_params.each do |param|
+        if params[param].class == Array
+          cache_key += params[param].join('-')
+        else
+          cache_key += params[param].to_s
+        end
+        cache_key += '/' unless (param == search_params.last)
+      end
+      cache_key
     end
 
   end
diff --git a/app/repositories/orient_db/relation.rb b/app/repositories/orient_db/relation.rb
index 3105e389032b79dc9119a87b0b6083f88b77a832..2d2bbcbacdcd6a487b5ea171abf8600d9e7a1474 100644
--- a/app/repositories/orient_db/relation.rb
+++ b/app/repositories/orient_db/relation.rb
@@ -2,7 +2,7 @@ module OrientDb
 
   ##abstract class Relation
   class Relation
-
+    
     def can_create?
       raise NotImplementedError, 'Relation#can_execute? is an abstract method.'
     end
diff --git a/app/repositories/orient_db/relation_chain.rb b/app/repositories/orient_db/relation_chain.rb
new file mode 100644
index 0000000000000000000000000000000000000000..28f04db1064d9303eec7fa97d0311697a808ff68
--- /dev/null
+++ b/app/repositories/orient_db/relation_chain.rb
@@ -0,0 +1,18 @@
+module OrientDb
+  class RelationChain
+    attr_reader :object
+
+    def initialize(object)
+      @object = object
+    end
+
+    def create
+      relations.each { |relation| relation.create }
+    end
+
+    def relations
+      raise NotImplementedError, 'RelationChain#relations is an abstract method.'
+    end
+
+  end
+end
\ No newline at end of file
diff --git a/app/repositories/orient_db/subject/relation.rb b/app/repositories/orient_db/subject/relation.rb
new file mode 100644
index 0000000000000000000000000000000000000000..df88a69c76714eadcaf609221966f0a6632e8758
--- /dev/null
+++ b/app/repositories/orient_db/subject/relation.rb
@@ -0,0 +1,12 @@
+module OrientDb
+  module Subject
+    class Relation < OrientDb::Relation
+      include OrientDb::Methods::EdgeMethods
+
+      def initialize(subject)
+        @subject = subject
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/repositories/orient_db/subject/relations_chain.rb b/app/repositories/orient_db/subject/relations_chain.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3ef3ba941ec1076d717a2f86c0fa11c4525bcd32
--- /dev/null
+++ b/app/repositories/orient_db/subject/relations_chain.rb
@@ -0,0 +1,14 @@
+module OrientDb
+  module Subject
+    class RelationsChain < OrientDb::RelationChain
+
+      def relations
+        [
+            OrientDb::Subject::SubtopicsRelations.new(object),
+            OrientDb::Subject::SupertopicsRelations.new(object)
+        ]
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/repositories/orient_db/subject/subtopics_relations.rb b/app/repositories/orient_db/subject/subtopics_relations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f93468274ba86bbfea4ecbed84823380609b9b6b
--- /dev/null
+++ b/app/repositories/orient_db/subject/subtopics_relations.rb
@@ -0,0 +1,17 @@
+module OrientDb
+  module Subject
+    class SubtopicsRelations < Relation
+
+      def can_create?
+        !@subject.subtopics.empty?
+      end
+
+      protected
+
+      def execute
+        create_edges_from_array("Subtopic", @subject.id, @subject.subtopics, true, false)
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/repositories/orient_db/subject/supertopics_relations.rb b/app/repositories/orient_db/subject/supertopics_relations.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b8e664dfd2081a35825b7f1701889b30dd9ca4e3
--- /dev/null
+++ b/app/repositories/orient_db/subject/supertopics_relations.rb
@@ -0,0 +1,17 @@
+module OrientDb
+  module Subject
+    class SupertopicsRelations < Relation
+
+      def can_create?
+        !@subject.supertopics.empty?
+      end
+
+      protected
+
+      def execute
+        create_edges_from_array("Subtopic", @subject.id, @subject.supertopics, true)
+      end
+
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/repositories/orient_db/subject_repository.rb b/app/repositories/orient_db/subject_repository.rb
index a7601ebe7a53caf040f4e2217ed4704c8fdaa948..afb89773dac1d8dae923294849a10a913d5863c5 100644
--- a/app/repositories/orient_db/subject_repository.rb
+++ b/app/repositories/orient_db/subject_repository.rb
@@ -44,14 +44,7 @@ module OrientDb
     end
 
     def create_relations(subject)
-      edges = []
-      unless subject.supertopics.empty?
-        edges << create_edges_from_array("Subtopic", subject.id, subject.supertopics, true)
-      end
-      unless subject.subtopics.empty?
-        edges << create_edges_from_array("Subtopic", subject.id, subject.subtopics, true, false)
-      end
-      edges.flatten
+      OrientDb::Subject::RelationsChain.new(subject).create
     end
 
     def build_hash(object)
@@ -61,23 +54,7 @@ module OrientDb
     end
 
     def build_object(args={})
-      subject = nil
-      unless args.nil?
-        subject = Subject.new(:id => args["@rid"])
-        args.each do |var, val|
-          var_name = "@"+var
-          if subject.respond_to?(var) && var != 'highlights'
-            subject.instance_variable_set(var_name, val)
-          end
-        end
-      end
-      subject
-    end
-
-    private
-
-    def odb_class
-      "Subject"
+      SubjectBuilder.build_from_orientdb args
     end
 
   end
diff --git a/app/repositories/orient_db/user_repository.rb b/app/repositories/orient_db/user_repository.rb
index 5d482f8fee7ebc425650bd85a5c57bc54cbce8d8..30bccb7f1b14f488ce802b167fdd3ab6ade5fd77 100644
--- a/app/repositories/orient_db/user_repository.rb
+++ b/app/repositories/orient_db/user_repository.rb
@@ -32,12 +32,5 @@ module OrientDb
       (result.count > 0)
     end
 
-
-    private
-
-    def odb_class
-      "User"
-    end
-
   end
 end
diff --git a/app/views/collections/list.html.erb b/app/views/collections/list.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..15f03b62ff298d2bf2242d86fd582c4143f78710
--- /dev/null
+++ b/app/views/collections/list.html.erb
@@ -0,0 +1,26 @@
+<div class="modal fade" id="collections-modal">
+  <div class="modal-dialog">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+        <h4 class="modal-title">Coleções</h4>
+      </div>
+      <form id="collections-modal-form">
+        <div class="modal-body">
+            <% if @learning_object.blank? %>
+              <% @collections.each do |collection| %>
+                <% unless collection.id == @collection.id %>
+                  <input type="checkbox" class="collection-element" id="<%= collection.id %>" name="collections" value="<%= collection.id %>">
+                  <label for="<%= collection.id %>"><%= collection.name %></label><br/>
+                <% end %>
+              <% end %>
+            <% end %>
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
+          <button type="submit" class="btn btn-primary">Enviar</button>
+        </div>
+      </form>
+    </div>
+  </div>
+</div>
diff --git a/app/views/collections/show.html.erb b/app/views/collections/show.html.erb
index 4acaf646dc45c19bfff77c8fbedb0310c38a6213..17b645d8fd4d9ca70a283969e0a7abe52b1d2ab6 100644
--- a/app/views/collections/show.html.erb
+++ b/app/views/collections/show.html.erb
@@ -1,5 +1,5 @@
-<nav class="navigation navbar-default "><br/>
-
+<nav class="navigation navbar-default collection-show-page" data-cid="<%= @collection.id %>">
+  <br/>
   <div class="container-fluid">
     <div class="navbar-right" style="text-align:right">
       <% if @own && @collection.class != Bookmarks %>
@@ -32,31 +32,31 @@
   </div>
   <br/>
 </nav>
-<!--<nav class="navigation navbar-inverse ">
+<nav class="navigation navbar-inverse collection-show-select-nav" style="display:none;">
   <div class="container-fluid">
-    <a class="navbar-brand" href="#"><span style="color: white">x arquivo(s) selecionado(s)</span></a>
+    <a class="navbar-brand" href="javascript:void(0);" data-toggle="tooltip" data-placement="bottom" title="Limpar seleção"></a>
     <ul class="nav navbar-nav navbar-right">
-      <li class="set-align">
-        <a href="#"><span class="left-edge1"><%= image_tag image_path("icons/Download_01.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
+      <li class="set-align collection-button" data-action="download">
+        <a href="javascript:void(0);"><span class="left-edge1"><%= image_tag image_path("icons/Download_01.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
           Salvar no <br>computador</span></a>
       </li>
-      <li class="set-align">
-        <a href="#"><span class="left-edge1"><%= image_tag image_path("icons/Copiar_Seleção.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
+      <li class="set-align collection-button" data-action="copy">
+        <a href="javascript:void(0);"><span class="left-edge1"><%= image_tag image_path("icons/Copiar_Seleção.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
           Copiar <br>para</span></a>
       </li>
       <% if @own %>
-        <li class="set-align">
-          <a href="#"><span class="left-edge1"><%= image_tag image_path("icons/Mover_Seleção.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
+        <li class="set-align collection-button" data-action="move">
+          <a href="javascript:void(0);"><span class="left-edge1"><%= image_tag image_path("icons/Mover_Seleção.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
             Mover <br>para</span></a>
         </li>
-        <li class="set-align">
-          <a href="#"><span class="left-edge1"><%= image_tag image_path("icons/Remover_da_Coleção_Seleção.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
+        <li class="set-align collection-button" data-action="remove">
+          <a href="javascript:void(0);"><span class="left-edge1"><%= image_tag image_path("icons/Remover_da_Coleção_Seleção.png"), class: "logo-image", size: "35x35" %></span><span style="color: white">
             Remover da <br>coleção</span></a>
         </li>
       <% end %>
     </ul>
   </div>
-</nav>-->
+</nav>
 
 <div class="row learning-object-columns">
   <br/>
diff --git a/app/views/learning_objects/_learning_object_vertical.erb b/app/views/learning_objects/_learning_object_vertical.erb
index 3fbb35213a5f00e367c45a46a88bd12925410c58..50156e91a5d71e5c8a1d031ca628320e16ab6ec1 100644
--- a/app/views/learning_objects/_learning_object_vertical.erb
+++ b/app/views/learning_objects/_learning_object_vertical.erb
@@ -1,4 +1,4 @@
-<div class="learning-object-vertical">
+<div class="learning-object-vertical" data-loid="<%= learning_object.id %>">
   <div class="panel">
     <div class="learning-object-thumbnail">
       <%= link_to learning_object_path(id: learning_object.id) do
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 94a42701e051fa741bd6d4ba3915dbb203b137b0..fb4db2e273e372831f48699952cf0c09712ab0f5 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -20,14 +20,13 @@
       </div>
     </div>
 
-    <div class="row learning-object-columns">
-      <%= render @objects[0], orientation: "vertical" %>
-      <%= render @objects[1], orientation: "vertical" %>
-      <%= render @objects[2], orientation: "vertical" %>
-      <%= render @objects[0], orientation: "vertical" %>
-      <%= render @objects[1], orientation: "vertical" %>
-      <%= render @objects[2], orientation: "vertical" %>
-    </div>
+    <% if @objects.count > 0 %>
+        <div class="row learning-object-columns">
+          <% @objects.each do |object| %>
+              <%= render object, orientation: "vertical" %>
+          <% end %>
+        </div>
+    <% end %>
 
 
     <div style="clear: both;"></div>
diff --git a/config/routes.rb b/config/routes.rb
index 8f9fe1a315fa633296b4838fe14e298e0326eb59..44d23cbf108917c170fbfb9c69607449ede56f05 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -67,13 +67,21 @@ Rails.application.routes.draw do
 
   resources :collections do
     member do
+      # collection list
+      get :list
+
       # add a learning object for some collection
       post '/learning_object/:learning_object_id', as: :add_learning_object, action: :add_learning_object
 
       # remove a learning object for some collection
       delete '/learning_object/:learning_object_id', as: :destroy_learning_object, action: :remove_learning_object
 
+      # change privacy
       post :change_privacy
+
+      # copy / move learning_objects
+      get '/copy', as: :copy_learning_objects, action: :copy_learning_objects
+      get '/move', as: :move_learning_objects, action: :move_learning_objects
     end
   end