iqvoc 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +69 -0
- data/Gemfile.lock +134 -0
- data/LICENSE +13 -0
- data/README.md +68 -0
- data/Rakefile +23 -0
- data/app/controllers/application_controller.rb +125 -0
- data/app/controllers/collections/hierarchical_controller.rb +44 -0
- data/app/controllers/collections_controller.rb +124 -0
- data/app/controllers/concepts/alphabetical_controller.rb +39 -0
- data/app/controllers/concepts/hierarchical_controller.rb +74 -0
- data/app/controllers/concepts/untranslated_controller.rb +38 -0
- data/app/controllers/concepts/versions_controller.rb +119 -0
- data/app/controllers/concepts_controller.rb +174 -0
- data/app/controllers/dashboard_controller.rb +43 -0
- data/app/controllers/pages_controller.rb +22 -0
- data/app/controllers/rdf_controller.rb +43 -0
- data/app/controllers/search_results_controller.rb +101 -0
- data/app/controllers/triple_store_syncs_controller.rb +45 -0
- data/app/controllers/user_sessions_controller.rb +48 -0
- data/app/controllers/users_controller.rb +81 -0
- data/app/helpers/application_helper.rb +60 -0
- data/app/helpers/concepts_helper.rb +86 -0
- data/app/helpers/dashboard_helper.rb +46 -0
- data/app/helpers/rdf_helper.rb +63 -0
- data/app/helpers/search_results_helper.rb +32 -0
- data/app/models/collection/base.rb +161 -0
- data/app/models/collection/member/base.rb +23 -0
- data/app/models/collection/member/collection.rb +33 -0
- data/app/models/collection/member/concept.rb +33 -0
- data/app/models/collection/unordered.rb +18 -0
- data/app/models/concept/base.rb +418 -0
- data/app/models/concept/relation/base.rb +95 -0
- data/app/models/concept/relation/reverse_relation_extension.rb +49 -0
- data/app/models/concept/relation/skos/base.rb +37 -0
- data/app/models/concept/relation/skos/broader/base.rb +41 -0
- data/app/models/concept/relation/skos/broader/mono.rb +28 -0
- data/app/models/concept/relation/skos/broader/poly.rb +23 -0
- data/app/models/concept/relation/skos/narrower/base.rb +37 -0
- data/app/models/concept/relation/skos/related.rb +21 -0
- data/app/models/concept/skos/base.rb +28 -0
- data/app/models/label/base.rb +98 -0
- data/app/models/label/skos/base.rb +27 -0
- data/app/models/labeling/base.rb +81 -0
- data/app/models/labeling/skos/alt_label.rb +21 -0
- data/app/models/labeling/skos/base.rb +99 -0
- data/app/models/labeling/skos/hidden_label.rb +25 -0
- data/app/models/labeling/skos/pref_label.rb +30 -0
- data/app/models/match/base.rb +57 -0
- data/app/models/match/skos/base.rb +23 -0
- data/app/models/match/skos/broad_match.rb +21 -0
- data/app/models/match/skos/close_match.rb +21 -0
- data/app/models/match/skos/exact_match.rb +21 -0
- data/app/models/match/skos/mapping_relation.rb +21 -0
- data/app/models/match/skos/narrow_match.rb +21 -0
- data/app/models/match/skos/related_match.rb +21 -0
- data/app/models/note/annotated/base.rb +29 -0
- data/app/models/note/base.rb +127 -0
- data/app/models/note/skos/base.rb +52 -0
- data/app/models/note/skos/change_note.rb +38 -0
- data/app/models/note/skos/definition.rb +33 -0
- data/app/models/note/skos/editorial_note.rb +21 -0
- data/app/models/note/skos/example.rb +21 -0
- data/app/models/note/skos/history_note.rb +21 -0
- data/app/models/note/skos/scope_note.rb +21 -0
- data/app/models/origin_mapping.rb +58 -0
- data/app/models/rdf_store.rb +96 -0
- data/app/models/search_extension.rb +58 -0
- data/app/models/user.rb +49 -0
- data/app/models/user_session.rb +23 -0
- data/app/views/collections/_collection.html.erb +10 -0
- data/app/views/collections/_form.html.erb +47 -0
- data/app/views/collections/edit.html.erb +11 -0
- data/app/views/collections/index.html.erb +12 -0
- data/app/views/collections/new.html.erb +7 -0
- data/app/views/collections/show.html.erb +53 -0
- data/app/views/collections/show.iqrdf +22 -0
- data/app/views/concepts/_base_data.html.erb +72 -0
- data/app/views/concepts/_close_match.html.erb +16 -0
- data/app/views/concepts/_show_head.html.erb +23 -0
- data/app/views/concepts/_visualization.html.erb +9 -0
- data/app/views/concepts/alphabetical/_pref_labeling.html.erb +6 -0
- data/app/views/concepts/alphabetical/index.html.erb +17 -0
- data/app/views/concepts/edit.html.erb +32 -0
- data/app/views/concepts/hierarchical/_treeview.html.erb +20 -0
- data/app/views/concepts/hierarchical/index.html.erb +5 -0
- data/app/views/concepts/index.iqrdf +24 -0
- data/app/views/concepts/new.html.erb +3 -0
- data/app/views/concepts/show_published.html.erb +16 -0
- data/app/views/concepts/show_unpublished.html.erb +43 -0
- data/app/views/concepts/untranslated/index.html.erb +23 -0
- data/app/views/dashboard/index.html.erb +47 -0
- data/app/views/errors/access_denied.html.erb +3 -0
- data/app/views/errors/multiple_choices.html.erb +11 -0
- data/app/views/errors/not_found.html.erb +8 -0
- data/app/views/kaminari/_page.html.erb +6 -0
- data/app/views/kaminari/_paginator.html.erb +15 -0
- data/app/views/layouts/_controls.html.erb +37 -0
- data/app/views/layouts/_header.html.erb +1 -0
- data/app/views/layouts/_navigation.html.erb +27 -0
- data/app/views/layouts/_sections.html.erb +8 -0
- data/app/views/layouts/application.html.erb +83 -0
- data/app/views/pages/about.html.erb +77 -0
- data/app/views/partials/_rdf_logo.html.erb +4 -0
- data/app/views/partials/collection/_member.html.erb +14 -0
- data/app/views/partials/collection_label/_search_result.html.erb +5 -0
- data/app/views/partials/concept/_edit_link_base.html.erb +4 -0
- data/app/views/partials/concept/_inline_base.html.erb +4 -0
- data/app/views/partials/concept/_new_link_base.html.erb +4 -0
- data/app/views/partials/concept/relation/_base.html.erb +8 -0
- data/app/views/partials/concept/relation/_edit_base.html.erb +15 -0
- data/app/views/partials/concept/relation/skos/_narrower.html.erb +12 -0
- data/app/views/partials/concept/relation/skos/broader/_mono.html.erb +28 -0
- data/app/views/partials/concept/relation/skos/broader/_poly.html.erb +14 -0
- data/app/views/partials/labeling/skos/_base.html.erb +17 -0
- data/app/views/partials/labeling/skos/_edit_base.html.erb +7 -0
- data/app/views/partials/labeling/skos/_search_result.html.erb +12 -0
- data/app/views/partials/match/_base.html.erb +13 -0
- data/app/views/partials/match/_edit_base.html.erb +6 -0
- data/app/views/partials/note/_base.html.erb +15 -0
- data/app/views/partials/note/_edit_base.html.erb +28 -0
- data/app/views/partials/note/_note.html.erb +14 -0
- data/app/views/partials/note/_search_result.html.erb +8 -0
- data/app/views/partials/note/skos/_edit_change_note.html.erb +47 -0
- data/app/views/partials/note/skos/definition/_search_result.html.erb +8 -0
- data/app/views/rdf/show_concept.iqrdf +5 -0
- data/app/views/search_results/_head_contents.html.erb +4 -0
- data/app/views/search_results/_rdf_links.html.erb +4 -0
- data/app/views/search_results/index.html.erb +92 -0
- data/app/views/search_results/index.iqrdf +33 -0
- data/app/views/triple_store_syncs/new.html.erb +7 -0
- data/app/views/user_sessions/new.html.erb +11 -0
- data/app/views/users/_form.html.erb +45 -0
- data/app/views/users/_user_preference.html.erb +12 -0
- data/app/views/users/edit.html.erb +14 -0
- data/app/views/users/index.html.erb +29 -0
- data/app/views/users/new.html.erb +13 -0
- data/config/application.rb +82 -0
- data/config/boot.rb +29 -0
- data/config/database.template.yml +43 -0
- data/config/database.yml +40 -0
- data/config/deploy/common.rb +79 -0
- data/config/deploy/ec2.rb +43 -0
- data/config/deploy/history.rb +29 -0
- data/config/deploy/innoq.rb +37 -0
- data/config/deploy.rb +72 -0
- data/config/engine.rb +25 -0
- data/config/environment.rb +21 -0
- data/config/environments/development.rb +74 -0
- data/config/environments/production.rb +65 -0
- data/config/environments/production.template.rb +65 -0
- data/config/environments/production_internal.rb +65 -0
- data/config/environments/test.rb +51 -0
- data/config/initializers/action_view.rb +23 -0
- data/config/initializers/active_record.rb +18 -0
- data/config/initializers/backtrace_silencers.rb +23 -0
- data/config/initializers/inflections.rb +26 -0
- data/config/initializers/iqvoc.rb +50 -0
- data/config/initializers/jdbc.rb +23 -0
- data/config/initializers/kaminari_config.rb +8 -0
- data/config/initializers/language.rb +6 -0
- data/config/initializers/mime_types.rb +24 -0
- data/config/initializers/secret_token.rb +29 -0
- data/config/initializers/secret_token.rb.template +29 -0
- data/config/initializers/session_store.rb +24 -0
- data/config/locales/activerecord.de.yml +135 -0
- data/config/locales/activerecord.en.yml +135 -0
- data/config/locales/authlogic.de.yml +38 -0
- data/config/locales/authlogic.en.yml +38 -0
- data/config/locales/de.yml +326 -0
- data/config/locales/defaults.de.yml +153 -0
- data/config/locales/en.yml +332 -0
- data/config/routes.rb +53 -0
- data/config/warble.rb +158 -0
- data/db/iqvoc_test.sqlite3 +0 -0
- data/db/migrate/20100927101502_create_schema.rb +174 -0
- data/db/migrate/20101125141218_add_collection_tables.rb +32 -0
- data/db/migrate/20101129161528_add_type_to_collections.rb +24 -0
- data/db/migrate/20101202094602_add_origin_to_collections.rb +25 -0
- data/db/migrate/20101202135420_rename_collection_contents_to_collection_members.rb +25 -0
- data/db/migrate/20101208103531_add_type_to_collection_contents.rb +27 -0
- data/db/migrate/20101210153916_add_indexes_to_collections.rb +25 -0
- data/db/migrate/20110204121244_create_collection_labels.rb +32 -0
- data/db/migrate/20110208084250_change_origin_lengths.rb +27 -0
- data/db/migrate/20110328124300_discard_collection_specifics.rb +27 -0
- data/db/migrate/20110408120357_remove_classifications_and_classifiers.rb +32 -0
- data/db/migrate/20110408120740_remove_xl_specfic_stuff.rb +39 -0
- data/db/migrate/20110420133640_change_value_in_notes.rb +8 -0
- data/db/migrate/20110427120534_add_published_at_to_labels.rb +9 -0
- data/db/migrate/20110510162719_use_mono_hierarchy_instead_of_poly_hierarchy.rb +13 -0
- data/db/migrate/20110512132624_extend_notes_value_field_length.rb +8 -0
- data/db/migrate/20110525103100_separate_note_annotation_predicates.rb +38 -0
- data/db/migrate/20110615134040_change_umt_note_annotations_to_dct.rb +9 -0
- data/db/schema.rb +127 -0
- data/db/seeds.rb +37 -0
- data/iqvoc.gemspec +27 -0
- data/lib/engine_tasks/assets.rake +49 -0
- data/lib/engine_tasks/db.rake +18 -0
- data/lib/engine_tasks/release.rake +118 -0
- data/lib/iqvoc/ability.rb +44 -0
- data/lib/iqvoc/data_helper.rb +27 -0
- data/lib/iqvoc/deep_cloning.rb +92 -0
- data/lib/iqvoc/rdf_helper.rb +67 -0
- data/lib/iqvoc/skos_importer.rb +144 -0
- data/lib/iqvoc/version.rb +19 -0
- data/lib/iqvoc/versioning.rb +151 -0
- data/lib/iqvoc.rb +228 -0
- data/lib/maker.rb +144 -0
- data/lib/ojdbc14.jar +0 -0
- data/lib/string.rb +23 -0
- data/lib/tasks/importer.rake +16 -0
- data/lib/tasks/jdbc.rake +24 -0
- data/public/404.html +26 -0
- data/public/422.html +26 -0
- data/public/500.html +26 -0
- data/public/favicon.ico +0 -0
- data/public/images/iqvoc/add.png +0 -0
- data/public/images/iqvoc/arrow_down.gif +0 -0
- data/public/images/iqvoc/arrow_up.gif +0 -0
- data/public/images/iqvoc/footer.png +0 -0
- data/public/images/iqvoc/go_there.png +0 -0
- data/public/images/iqvoc/header.png +0 -0
- data/public/images/iqvoc/header_long.png +0 -0
- data/public/images/iqvoc/iqvoc.png +0 -0
- data/public/images/iqvoc/note_add.png +0 -0
- data/public/images/iqvoc/note_delete.png +0 -0
- data/public/images/iqvoc/note_edit.png +0 -0
- data/public/images/iqvoc/ok.png +0 -0
- data/public/images/iqvoc/rails.png +0 -0
- data/public/images/iqvoc/rdf_flyer.gif +0 -0
- data/public/images/iqvoc/red_arrow.png +0 -0
- data/public/images/iqvoc/remove.png +0 -0
- data/public/images/iqvoc/shadow.png +0 -0
- data/public/images/iqvoc/spinner.gif +0 -0
- data/public/images/iqvoc/tokenizer_delete.png +0 -0
- data/public/images/iqvoc/tokenizer_pencile.png +0 -0
- data/public/images/iqvoc/tokenizer_show.png +0 -0
- data/public/images/iqvoc/unfinished.png +0 -0
- data/public/javascripts/iqvoc/application.js +123 -0
- data/public/javascripts/iqvoc/entityselect.js +121 -0
- data/public/javascripts/iqvoc/excanvas.js +35 -0
- data/public/javascripts/iqvoc/iqvoc.js +118 -0
- data/public/javascripts/iqvoc/jit_rgraph.js +153 -0
- data/public/javascripts/iqvoc/jquery-1.6.2.min.js +18 -0
- data/public/javascripts/iqvoc/jquery-treeview/changelog.txt +29 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/async.html +44 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/bg.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/demo.js +43 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/images.html +56 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/index.html +340 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/large.html +559 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/prerendered.html +621 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/screen.css +24 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/simple.html +82 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/source.php +87 -0
- data/public/javascripts/iqvoc/jquery-treeview/demo/source.phps +87 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/ajax-loader.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/file.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/folder-closed.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/folder.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/minus.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/plus.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-black-line.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-black.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-default-line.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-default.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-famfamfam-line.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-famfamfam.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-gray-line.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-gray.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-red-line.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/images/treeview-red.gif +0 -0
- data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.async.js +82 -0
- data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.css +75 -0
- data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.js +251 -0
- data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.min.js +15 -0
- data/public/javascripts/iqvoc/jquery-treeview/jquery.treeview.pack.js +16 -0
- data/public/javascripts/iqvoc/jquery-treeview/lib/jquery.cookie.js +92 -0
- data/public/javascripts/iqvoc/jquery-treeview/lib/jquery.js +3363 -0
- data/public/javascripts/iqvoc/jquery-treeview/todo +8 -0
- data/public/javascripts/iqvoc/jquery-ui-1.8.13.custom.js +3229 -0
- data/public/javascripts/iqvoc/jquery-ui-1.8.13.custom.min.js +163 -0
- data/public/javascripts/iqvoc/jquery-ui.datepicker-de.js +22 -0
- data/public/javascripts/iqvoc/json2.js +480 -0
- data/public/javascripts/iqvoc/langselect.js +73 -0
- data/public/javascripts/iqvoc/rails.js +132 -0
- data/public/javascripts/iqvoc/storage.js +122 -0
- data/public/javascripts/iqvoc/visualization.js +321 -0
- data/public/robots.txt +5 -0
- data/public/stylesheets/iqvoc/blueprint/ie.css +35 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/buttons/icons/cross.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/buttons/icons/key.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/buttons/icons/tick.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/buttons/readme.txt +32 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/buttons/screen.css +97 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/fancy-type/readme.txt +14 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/fancy-type/screen.css +71 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/doc.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/email.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/external.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/feed.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/im.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/pdf.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/visited.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/icons/xls.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/readme.txt +18 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/link-icons/screen.css +40 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/rtl/readme.txt +10 -0
- data/public/stylesheets/iqvoc/blueprint/plugins/rtl/screen.css +110 -0
- data/public/stylesheets/iqvoc/blueprint/print.css +29 -0
- data/public/stylesheets/iqvoc/blueprint/screen.css +258 -0
- data/public/stylesheets/iqvoc/blueprint/src/forms.css +65 -0
- data/public/stylesheets/iqvoc/blueprint/src/grid.css +280 -0
- data/public/stylesheets/iqvoc/blueprint/src/grid.png +0 -0
- data/public/stylesheets/iqvoc/blueprint/src/ie.css +76 -0
- data/public/stylesheets/iqvoc/blueprint/src/print.css +85 -0
- data/public/stylesheets/iqvoc/blueprint/src/reset.css +45 -0
- data/public/stylesheets/iqvoc/blueprint/src/typography.css +106 -0
- data/public/stylesheets/iqvoc/forms.css +71 -0
- data/public/stylesheets/iqvoc/images/back.png +0 -0
- data/public/stylesheets/iqvoc/images/branch.png +0 -0
- data/public/stylesheets/iqvoc/images/categ.png +0 -0
- data/public/stylesheets/iqvoc/images/categ_open.png +0 -0
- data/public/stylesheets/iqvoc/images/go_there.png +0 -0
- data/public/stylesheets/iqvoc/images/iqvoc.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_end.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_end_filled.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_mid.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_mid_filled.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_nothing.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_only.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_only_filled.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_top.png +0 -0
- data/public/stylesheets/iqvoc/images/leaf_top_filled.png +0 -0
- data/public/stylesheets/iqvoc/images/nothing.png +0 -0
- data/public/stylesheets/iqvoc/images/top_01.png +0 -0
- data/public/stylesheets/iqvoc/images/trunk.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_flat_55_fbec88_40x100.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_217bc0_256x240.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_2e83ff_256x240.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_469bdd_256x240.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_6da8d5_256x240.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_d8e7f3_256x240.png +0 -0
- data/public/stylesheets/iqvoc/images/ui-icons_f9bd01_256x240.png +0 -0
- data/public/stylesheets/iqvoc/iqvoc.css +477 -0
- data/public/stylesheets/iqvoc/jquery-ui-1.8.13.custom.css +415 -0
- data/public/stylesheets/iqvoc/widgets.css +81 -0
- data/test/factories.rb +74 -0
- data/test/integration/alphabetical_test.rb +53 -0
- data/test/integration/authentication_test.rb +41 -0
- data/test/integration/browse_concepts_and_labels_test.rb +61 -0
- data/test/integration/browse_static_pages_test.rb +29 -0
- data/test/integration/client_augmentation_test.rb +42 -0
- data/test/integration/client_edit_concept_test.rb +72 -0
- data/test/integration/collection_circularity_test.rb +110 -0
- data/test/integration/concept_test.rb +61 -0
- data/test/integration/edit_concepts_test.rb +40 -0
- data/test/integration/note_annotations_test.rb +86 -0
- data/test/integration/search_test.rb +205 -0
- data/test/integration/tree_test.rb +31 -0
- data/test/integration/untranslated_test.rb +60 -0
- data/test/integration_test_helper.rb +45 -0
- data/test/performance/browsing_test.rb +25 -0
- data/test/test_helper.rb +29 -0
- data/test/unit/concept_test.rb +93 -0
- data/test/unit/note_test.rb +32 -0
- data/test/unit/origin_mapping_test.rb +70 -0
- data/test/unit/skos_import_test.rb +100 -0
- metadata +522 -0
@@ -0,0 +1,418 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class Concept::Base < ActiveRecord::Base
|
18
|
+
|
19
|
+
set_table_name 'concepts'
|
20
|
+
|
21
|
+
include Iqvoc::Versioning
|
22
|
+
|
23
|
+
class_inheritable_accessor :default_includes
|
24
|
+
self.default_includes = []
|
25
|
+
|
26
|
+
class_inheritable_accessor :rdf_namespace, :rdf_class
|
27
|
+
self.rdf_namespace = nil
|
28
|
+
self.rdf_class = nil
|
29
|
+
|
30
|
+
# ********** Validations
|
31
|
+
|
32
|
+
validates :origin, :presence => true, :on => :update
|
33
|
+
|
34
|
+
validate :ensure_maximum_two_versions_of_a_concept,
|
35
|
+
:on => :create
|
36
|
+
|
37
|
+
validate :ensure_a_pref_label_in_the_primary_thesaurus_language,
|
38
|
+
:on => :update
|
39
|
+
|
40
|
+
validate :ensure_no_pref_labels_share_the_same_language
|
41
|
+
|
42
|
+
Iqvoc::Concept.include_modules.each do |mod|
|
43
|
+
include mod
|
44
|
+
end
|
45
|
+
|
46
|
+
# ********** Hooks
|
47
|
+
|
48
|
+
before_validation do |concept|
|
49
|
+
# Handle save or destruction of inline relations (relations or labelings)
|
50
|
+
# for use with widgets etc.
|
51
|
+
|
52
|
+
# Inline assigned SKOS::Labels
|
53
|
+
# @labelings_by_text # => {'relation_name' => {'lang' => 'label1, label2, ...'}}
|
54
|
+
(@labelings_by_text ||= {}).each do |relation_name, lang_values|
|
55
|
+
relation_name = relation_name.to_s
|
56
|
+
reflection = self.class.reflections.stringify_keys[relation_name]
|
57
|
+
labeling_class = reflection && reflection.class_name && reflection.class_name.constantize
|
58
|
+
if labeling_class && labeling_class < Labeling::Base
|
59
|
+
self.send(relation_name).all.map(&:destroy)
|
60
|
+
lang_values = {nil => lang_values.first} if lang_values.is_a?(Array) # For language = nil: <input name=bla[labeling_class][]> => Results in an Array!
|
61
|
+
lang_values.each do |lang, values|
|
62
|
+
values.split(Iqvoc::InlineDataHelper::Splitter).each do |value|
|
63
|
+
value.squish!
|
64
|
+
self.send(relation_name).build(:target => labeling_class.label_class.new(:value => value, :language => lang)) unless value.blank?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
after_save do |concept|
|
72
|
+
# Concept relations
|
73
|
+
# @concept_relations_by_id # => {'relation_name' => 'origin1, origin2, ...'}
|
74
|
+
(@concept_relations_by_id ||= {}).each do |relation_name, new_origins|
|
75
|
+
new_origins = new_origins.split(Iqvoc::InlineDataHelper::Splitter).map(&:squish)
|
76
|
+
existing_origins = concept.send(relation_name).map { |r| r.target.origin }.uniq
|
77
|
+
Concept::Base.by_origin(new_origins - existing_origins).each do |c| # Iterate over all concepts to be added
|
78
|
+
concept.send(relation_name).create_with_reverse_relation(c)
|
79
|
+
end
|
80
|
+
concept.send(relation_name).by_target_origin(existing_origins - new_origins).each do |relation| # Iterate over all concepts to be removed
|
81
|
+
concept.send(relation_name).destroy_with_reverse_relation(relation.target)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
after_save do |concept|
|
87
|
+
# Generate a origin if none was given yet
|
88
|
+
if concept.origin.blank?
|
89
|
+
raise "Concept::Base#after_save (generate origin): Unable to set the origin by id!" unless concept.id
|
90
|
+
concept.reload
|
91
|
+
concept.origin = sprintf("_%08d", concept.id)
|
92
|
+
concept.save! # On exception the complete save transaction will be rolled back
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# ********** "Static"/unconfigureable relations
|
97
|
+
|
98
|
+
@nested_relations = [] # Will be marked as nested attributes later
|
99
|
+
|
100
|
+
has_many :relations, :foreign_key => 'owner_id', :class_name => "Concept::Relation::Base", :dependent => :destroy
|
101
|
+
has_many :related_concepts, :through => :relations, :source => :target
|
102
|
+
has_many :referenced_relations, :foreign_key => 'target_id', :class_name => "Concept::Relation::Base", :dependent => :destroy
|
103
|
+
include_to_deep_cloning(:relations, :referenced_relations)
|
104
|
+
|
105
|
+
has_many :labelings, :foreign_key => 'owner_id', :class_name => "Labeling::Base", :dependent => :destroy
|
106
|
+
has_many :labels, :through => :labelings, :source => :target
|
107
|
+
# Deep cloning has to be done in specific relations. S. pref_labels etc
|
108
|
+
|
109
|
+
has_many :notes, :class_name => "Note::Base", :as => :owner, :dependent => :destroy
|
110
|
+
include_to_deep_cloning({:notes => :annotations})
|
111
|
+
|
112
|
+
has_many :matches, :foreign_key => 'concept_id', :class_name => "Match::Base", :dependent => :destroy
|
113
|
+
include_to_deep_cloning(:matches)
|
114
|
+
|
115
|
+
has_many :collection_members, :foreign_key => 'target_id', :class_name => "Collection::Member::Concept", :dependent => :destroy
|
116
|
+
has_many :collections, :through => :collection_members, :class_name => Iqvoc::Collection.base_class_name
|
117
|
+
include_to_deep_cloning(:collection_members)
|
118
|
+
|
119
|
+
# ************** "Dynamic"/configureable relations
|
120
|
+
|
121
|
+
# *** Concept2Concept relations
|
122
|
+
|
123
|
+
# Broader
|
124
|
+
# Actually this is not needed anymore.
|
125
|
+
# BUT: the include in scope :tops doesn't work with
|
126
|
+
# 'Iqvoc::Concept.broader_relation_class_name'!?!?! (Rails Bug????)
|
127
|
+
has_many :broader_relations,
|
128
|
+
:foreign_key => :owner_id,
|
129
|
+
:class_name => Iqvoc::Concept.broader_relation_class_name,
|
130
|
+
:extend => Concept::Relation::ReverseRelationExtension
|
131
|
+
|
132
|
+
# Narrower
|
133
|
+
# Actually this is not needed anymore.
|
134
|
+
# BUT: the include in scope :tops doesn't work with
|
135
|
+
# 'Iqvoc::Concept.broader_relation_class_name'!?!?! (Rails Bug????)
|
136
|
+
has_many :narrower_relations,
|
137
|
+
:foreign_key => :owner_id,
|
138
|
+
:class_name => Iqvoc::Concept.broader_relation_class.narrower_class.name,
|
139
|
+
:extend => Concept::Relation::ReverseRelationExtension
|
140
|
+
|
141
|
+
# Relations
|
142
|
+
# e.g. 'concept_relation_skos_relateds'
|
143
|
+
# Attention: Iqvoc::Concept.relation_class_names loads the Concept::Relation::*
|
144
|
+
# classes!
|
145
|
+
Iqvoc::Concept.relation_class_names.each do |relation_class_name|
|
146
|
+
has_many relation_class_name.to_relation_name,
|
147
|
+
:foreign_key => :owner_id,
|
148
|
+
:class_name => relation_class_name,
|
149
|
+
:extend => Concept::Relation::ReverseRelationExtension
|
150
|
+
end
|
151
|
+
|
152
|
+
# *** Labels/Labelings
|
153
|
+
|
154
|
+
has_many :pref_labelings,
|
155
|
+
:foreign_key => 'owner_id',
|
156
|
+
:class_name => Iqvoc::Concept.pref_labeling_class_name
|
157
|
+
|
158
|
+
has_many :pref_labels,
|
159
|
+
:through => :pref_labelings,
|
160
|
+
:source => :target
|
161
|
+
|
162
|
+
Iqvoc::Concept.labeling_class_names.each do |labeling_class_name, languages|
|
163
|
+
has_many labeling_class_name.to_relation_name,
|
164
|
+
:foreign_key => 'owner_id',
|
165
|
+
:class_name => labeling_class_name
|
166
|
+
# When a Label has only one labeling (the "no skosxl" case) we'll have to
|
167
|
+
# clone the label too.
|
168
|
+
if labeling_class_name.constantize.reflections[:target].options[:dependent] == :destroy
|
169
|
+
include_to_deep_cloning(labeling_class_name.to_relation_name => :target)
|
170
|
+
else
|
171
|
+
include_to_deep_cloning(labeling_class_name.to_relation_name)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# *** Matches (pointing to an other thesaurus)
|
176
|
+
|
177
|
+
Iqvoc::Concept.match_class_names.each do |match_class_name|
|
178
|
+
has_many match_class_name.to_relation_name,
|
179
|
+
:class_name => match_class_name,
|
180
|
+
:foreign_key => 'concept_id'
|
181
|
+
|
182
|
+
# Serialized setters and getters (\r\n or , separated) -- TODO: use Iqvoc::InlineDataHelper?
|
183
|
+
define_method("inline_#{match_class_name.to_relation_name}".to_sym) do
|
184
|
+
self.send(match_class_name.to_relation_name).map(&:value).join("\r\n")
|
185
|
+
end
|
186
|
+
|
187
|
+
define_method("inline_#{match_class_name.to_relation_name}=".to_sym) do |value|
|
188
|
+
urls = value.split(/\r\n|,/).map(&:strip).reject(&:blank?)
|
189
|
+
self.send(match_class_name.to_relation_name).each do |match|
|
190
|
+
if (urls.include?(match.value))
|
191
|
+
urls.delete(match.value) # We're done with that one
|
192
|
+
else
|
193
|
+
self.send(match_class_name.to_relation_name).destroy(match.id) # User deleted this one
|
194
|
+
end
|
195
|
+
end
|
196
|
+
urls.each do |url|
|
197
|
+
self.send(match_class_name.to_relation_name) << match_class_name.constantize.new(:value => url)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
# *** Notes
|
204
|
+
|
205
|
+
Iqvoc::Concept.note_class_names.each do |class_name|
|
206
|
+
relation_name = class_name.to_relation_name
|
207
|
+
has_many relation_name, :class_name => class_name, :as => :owner
|
208
|
+
@nested_relations << relation_name
|
209
|
+
end
|
210
|
+
|
211
|
+
# *** Further association classes (could be ranks or stuff like that)
|
212
|
+
|
213
|
+
Iqvoc::Concept.additional_association_classes.each do |association_class, foreign_key|
|
214
|
+
has_many association_class.name.to_relation_name, :class_name => association_class.name, :foreign_key => foreign_key, :dependent => :destroy
|
215
|
+
include_to_deep_cloning(association_class.deep_cloning_relations)
|
216
|
+
association_class.referenced_by(self)
|
217
|
+
end
|
218
|
+
|
219
|
+
# ********** Relation Stuff
|
220
|
+
|
221
|
+
@nested_relations.each do |relation|
|
222
|
+
accepts_nested_attributes_for relation, :allow_destroy => true, :reject_if => Proc.new {|attrs| attrs[:value].blank? }
|
223
|
+
end
|
224
|
+
|
225
|
+
# ********** Scopes
|
226
|
+
|
227
|
+
scope :tops, includes(:broader_relations).
|
228
|
+
where(:concept_relations => {:id => nil})
|
229
|
+
|
230
|
+
scope :broader_tops, includes(:narrower_relations, :pref_labels).
|
231
|
+
where(:concept_relations => {:id => nil}, :labelings => {:type => Iqvoc::Concept.pref_labeling_class_name}).
|
232
|
+
order("LOWER(#{Label::Base.table_name}.value)")
|
233
|
+
|
234
|
+
scope :with_associations, includes([
|
235
|
+
{:labelings => :target}, :relations, :matches, :notes
|
236
|
+
])
|
237
|
+
|
238
|
+
scope :with_pref_labels,
|
239
|
+
includes(:pref_labels).
|
240
|
+
order("LOWER(#{Label::Base.table_name}.value)").
|
241
|
+
where(:labelings => {:type => Iqvoc::Concept.pref_labeling_class_name}) # This line is just a workaround for a Rails Bug. TODO: Delete it when the Bug is fixed
|
242
|
+
|
243
|
+
scope :for_dashboard, lambda {
|
244
|
+
unpublished_or_follow_up.
|
245
|
+
includes(:pref_labels, :locking_user)
|
246
|
+
}
|
247
|
+
|
248
|
+
# ********** Class methods
|
249
|
+
|
250
|
+
def self.inline_partial_name
|
251
|
+
"partials/concept/inline_base"
|
252
|
+
end
|
253
|
+
|
254
|
+
def self.new_link_partial_name
|
255
|
+
"partials/concept/new_link_base"
|
256
|
+
end
|
257
|
+
|
258
|
+
def self.edit_link_partial_name
|
259
|
+
"partials/concept/edit_link_base"
|
260
|
+
end
|
261
|
+
|
262
|
+
# ********** Methods
|
263
|
+
|
264
|
+
def initialize(params = {})
|
265
|
+
super(params)
|
266
|
+
@full_validation = false
|
267
|
+
end
|
268
|
+
|
269
|
+
def labelings_by_text=(hash)
|
270
|
+
@labelings_by_text = hash
|
271
|
+
|
272
|
+
# For language = nil: <input name=bla[labeling_class][]> => Results in an Array!
|
273
|
+
@labelings_by_text.each do |relation_name, array_or_hash|
|
274
|
+
@labelings_by_text[relation_name] = {nil => array_or_hash.first} if array_or_hash.is_a?(Array)
|
275
|
+
end
|
276
|
+
|
277
|
+
@labelings_by_text
|
278
|
+
end
|
279
|
+
|
280
|
+
def labelings_by_text(relation_name, language)
|
281
|
+
(@labelings_by_text && @labelings_by_text[relation_name] && @labelings_by_text[relation_name][language]) ||
|
282
|
+
self.send(relation_name).by_label_language(language).
|
283
|
+
map { |l| l.target.value }.join(Iqvoc::InlineDataHelper::Joiner)
|
284
|
+
end
|
285
|
+
|
286
|
+
def concept_relations_by_id=(hash)
|
287
|
+
@concept_relations_by_id = hash
|
288
|
+
end
|
289
|
+
|
290
|
+
def concept_relations_by_id(relation_name)
|
291
|
+
(@concept_relations_by_id && @concept_relations_by_id[relation_name]) ||
|
292
|
+
self.send(relation_name).map { |l| l.target.origin }.
|
293
|
+
join(Iqvoc::InlineDataHelper::Joiner)
|
294
|
+
end
|
295
|
+
|
296
|
+
# returns the (one!) preferred label of a concept for the requested language.
|
297
|
+
# lang can either be a (lowercase) string or symbol with the (ISO ....) two letter
|
298
|
+
# code of the language (e.g. :en for English, :fr for French, :de for German).
|
299
|
+
# If no prefLabel for the requested language exists, a new label will be returned
|
300
|
+
# (if you modify it, don't forget to save it afterwards!)
|
301
|
+
def pref_label
|
302
|
+
lang = I18n.locale.to_s
|
303
|
+
@cached_pref_labels ||= pref_labels.each_with_object({}) do |label, hash|
|
304
|
+
if hash[label.language]
|
305
|
+
Rails.logger.warn("Two pref_labels (#{hash[label.language]}, #{label}) for one language (#{label.language}). Taking the second one.")
|
306
|
+
end
|
307
|
+
hash[label.language.to_s] = label
|
308
|
+
end
|
309
|
+
if @cached_pref_labels[lang].nil?
|
310
|
+
# Fallback to the main language
|
311
|
+
@cached_pref_labels[lang] = pref_labels.select{ |l|
|
312
|
+
l.language.to_s == Iqvoc::Concept.pref_labeling_languages.first.to_s
|
313
|
+
}.first
|
314
|
+
end
|
315
|
+
@cached_pref_labels[lang]
|
316
|
+
end
|
317
|
+
|
318
|
+
def labels_for_labeling_class_and_language(labeling_class, lang = :en, only_published = true)
|
319
|
+
# Convert lang to string in case it's not nil.
|
320
|
+
# nil values play their own role for labels without a language.
|
321
|
+
lang = lang.to_s unless lang.nil?
|
322
|
+
labeling_class = labeling_class.name if labeling_class < ActiveRecord::Base # Use the class name string
|
323
|
+
@labels ||= labelings.each_with_object({}) do |labeling, hash|
|
324
|
+
((hash[labeling.class.name.to_s] ||= {})[labeling.target.language] ||= []) << labeling.target if labeling.target
|
325
|
+
end
|
326
|
+
return ((@labels && @labels[labeling_class] && @labels[labeling_class][lang]) || []).select{|l| l.published? || !only_published}
|
327
|
+
end
|
328
|
+
|
329
|
+
def related_concepts_for_relation_class(relation_class, only_published = true)
|
330
|
+
relation_class = relation_class.name if relation_class < ActiveRecord::Base # Use the class name string
|
331
|
+
relations.select { |rel| rel.class.name == relation_class }.map(&:target).
|
332
|
+
select { |c| c.published? || !only_published }
|
333
|
+
end
|
334
|
+
|
335
|
+
def matches_for_class(match_class)
|
336
|
+
match_class = match_class.name if match_class < ActiveRecord::Base # Use the class name string
|
337
|
+
matches.select{ |match| match.class.name == match_class }
|
338
|
+
end
|
339
|
+
|
340
|
+
def notes_for_class(note_class)
|
341
|
+
note_class = note_class.name if note_class < ActiveRecord::Base # Use the class name string
|
342
|
+
notes.select{ |note| note.class.name == note_class }
|
343
|
+
end
|
344
|
+
|
345
|
+
# This shows up (in brackets) to the right of a concept link if it doesn't
|
346
|
+
# return nil
|
347
|
+
def additional_info
|
348
|
+
nil
|
349
|
+
end
|
350
|
+
|
351
|
+
def to_param
|
352
|
+
"#{origin}"
|
353
|
+
end
|
354
|
+
|
355
|
+
def to_s
|
356
|
+
pref_label.to_s
|
357
|
+
end
|
358
|
+
|
359
|
+
# TODO: rename to "publish!"
|
360
|
+
def save_with_full_validation!
|
361
|
+
@full_validation = true
|
362
|
+
save!
|
363
|
+
end
|
364
|
+
|
365
|
+
# TODO: rename to "publishable?"
|
366
|
+
def valid_with_full_validation?
|
367
|
+
@full_validation = true
|
368
|
+
valid?
|
369
|
+
end
|
370
|
+
|
371
|
+
# TODO: remove
|
372
|
+
def invalid_with_full_validation?
|
373
|
+
@full_validation = true
|
374
|
+
invalid?
|
375
|
+
end
|
376
|
+
|
377
|
+
def associated_objects_in_editing_mode
|
378
|
+
{
|
379
|
+
:concept_relations => Concept::Relation::Base.by_owner(id).target_in_edit_mode,
|
380
|
+
}
|
381
|
+
end
|
382
|
+
|
383
|
+
# ********** Validation methods
|
384
|
+
|
385
|
+
def ensure_maximum_two_versions_of_a_concept
|
386
|
+
if Concept::Base.by_origin(origin).count >= 2
|
387
|
+
errors.add :base, I18n.t("txt.models.concept.version_error")
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
def ensure_a_pref_label_in_the_primary_thesaurus_language
|
392
|
+
if @full_validation
|
393
|
+
labels = pref_labels.select{|l| l.published?}
|
394
|
+
if labels.count == 0
|
395
|
+
errors.add :base, I18n.t("txt.models.concept.no_pref_label_error")
|
396
|
+
elsif not labels.map(&:language).map(&:to_s).include?(Iqvoc::Concept.pref_labeling_languages.first.to_s)
|
397
|
+
errors.add :base, I18n.t("txt.models.concept.main_pref_label_language_missing_error")
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def ensure_no_pref_labels_share_the_same_language
|
403
|
+
# We have many sources a prefLabel can be defined in
|
404
|
+
pls = pref_labelings.map(&:target) +
|
405
|
+
send(Iqvoc::Concept.pref_labeling_class_name.to_relation_name).map(&:target) +
|
406
|
+
labelings.select{|l| l.is_a?(Iqvoc::Concept.pref_labeling_class)}.map(&:target)
|
407
|
+
languages = {}
|
408
|
+
pls.each do |pref_label|
|
409
|
+
lang = pref_label.language.to_s
|
410
|
+
origin = (pref_label.origin || pref_label.id || pref_label.value).to_s
|
411
|
+
if (languages.keys.include?(lang) && languages[lang] != origin)
|
412
|
+
errors.add :pref_labelings, I18n.t("txt.models.concept.pref_labels_with_same_languages_error")
|
413
|
+
end
|
414
|
+
languages[lang] = origin
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class Concept::Relation::Base < ActiveRecord::Base
|
18
|
+
|
19
|
+
# ATTENTION:
|
20
|
+
# This class (and the inheriting subclasses) should not reference the
|
21
|
+
# Concept::Base class directly at load time!
|
22
|
+
# This means that Concept::Base may not be loaded when this class is loaded!
|
23
|
+
# So use Concept::Base ONLY in methods or procs.
|
24
|
+
#
|
25
|
+
# The reason for this lies in the fact that Concept::Base calls the
|
26
|
+
# Concept::Relation::SKOS::Broader::Base.narrower_class method to create all
|
27
|
+
# concept_relation relations. This means Concept::Base triggers Rails to load
|
28
|
+
# the Concept::Relation::* classes. If this would trigger Rails to load
|
29
|
+
# Concept::Base we would have a loop == a problem.
|
30
|
+
|
31
|
+
set_table_name 'concept_relations'
|
32
|
+
|
33
|
+
class_inheritable_accessor :rdf_namespace, :rdf_predicate
|
34
|
+
self.rdf_namespace = nil
|
35
|
+
self.rdf_predicate = nil
|
36
|
+
|
37
|
+
# ********* Associations
|
38
|
+
|
39
|
+
belongs_to :owner, :class_name => "Concept::Base"
|
40
|
+
belongs_to :target, :class_name => "Concept::Base"
|
41
|
+
|
42
|
+
# ********* Scopes
|
43
|
+
|
44
|
+
scope :by_owner, lambda { |owner_id|
|
45
|
+
where(:owner_id => owner_id)
|
46
|
+
}
|
47
|
+
|
48
|
+
scope :by_owner_origin, lambda { |owner_id|
|
49
|
+
includes(:owner).merge(Concept::Base.by_origin(owner_id))
|
50
|
+
}
|
51
|
+
|
52
|
+
scope :by_target_origin, lambda { |owner_id|
|
53
|
+
includes(:target).merge(Concept::Base.by_origin(owner_id))
|
54
|
+
}
|
55
|
+
|
56
|
+
scope :target_editor_selectable, lambda { # Lambda because Concept::Base.editor_selectable is currently not known + we don't want to call it at load time!
|
57
|
+
includes(:target).merge(Concept::Base.editor_selectable)
|
58
|
+
}
|
59
|
+
|
60
|
+
scope :published, lambda { # Lambda because Concept::Base.published is currently not known + we don't want to call it at load time!
|
61
|
+
includes(:target).merge(Concept::Base.published)
|
62
|
+
}
|
63
|
+
|
64
|
+
scope :target_in_edit_mode, lambda { # Lambda because Concept::Base.in_edit_mode is currently not known + we don't want to call it at load time!
|
65
|
+
joins(:target).merge(Concept::Base.in_edit_mode)
|
66
|
+
}
|
67
|
+
|
68
|
+
# ********* Methods
|
69
|
+
|
70
|
+
def self.reverse_relation_class
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.view_section(obj)
|
75
|
+
"relations"
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.view_section_sort_key(obj)
|
79
|
+
100
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.partial_name(obj)
|
83
|
+
"partials/concept/relation/base"
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.edit_partial_name(obj)
|
87
|
+
"partials/concept/relation/edit_base"
|
88
|
+
end
|
89
|
+
|
90
|
+
# if `singular` is true, only a single occurrence is allowed per instance
|
91
|
+
def self.singular?
|
92
|
+
false
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
module Concept
|
18
|
+
module Relation
|
19
|
+
module ReverseRelationExtension
|
20
|
+
|
21
|
+
def create_with_reverse_relation(target_concept)
|
22
|
+
relation_class = proxy_reflection.class_name.constantize
|
23
|
+
ActiveRecord::Base.transaction do
|
24
|
+
# The one direction
|
25
|
+
scope = relation_class.where(:owner_id => proxy_owner.id, :target_id => target_concept.id)
|
26
|
+
scope.any? || scope.create!
|
27
|
+
|
28
|
+
# The reverse direction
|
29
|
+
scope = relation_class.reverse_relation_class.where(:owner_id => target_concept.id, :target_id => proxy_owner.id)
|
30
|
+
scope.any? || scope.create!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def destroy_with_reverse_relation(target_concept)
|
35
|
+
relation_class = proxy_reflection.class_name.constantize
|
36
|
+
ActiveRecord::Base.transaction do
|
37
|
+
relation_class.where(:owner_id => proxy_owner.id, :target_id => target_concept.id).all.each do |relation|
|
38
|
+
relation.destroy
|
39
|
+
end
|
40
|
+
|
41
|
+
relation_class.reverse_relation_class.where(:owner_id => target_concept.id, :target_id => proxy_owner.id).all.each do |relation|
|
42
|
+
relation.destroy
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class Concept::Relation::SKOS::Base < Concept::Relation::Base
|
18
|
+
|
19
|
+
self.rdf_namespace = 'skos'
|
20
|
+
|
21
|
+
def self.build_from_rdf(subject, predicate, object)
|
22
|
+
raise "Labeling::SKOS::Base#build_from_rdf: Subject (#{subject}) must be a Concept." unless subject.is_a?(Concept::Base)
|
23
|
+
raise "Labeling::SKOS::Base#build_from_rdf: Object (#{object}) must be a Concept." unless object.is_a?(Concept::Base)
|
24
|
+
|
25
|
+
if subject.send(self.name.to_relation_name).select{|rel| rel.target_id == object.id || rel.target == object}.empty?
|
26
|
+
subject.send(self.name.to_relation_name) << self.new(:target => object)
|
27
|
+
end
|
28
|
+
if self.reverse_relation_class && object.send(self.reverse_relation_class.name.to_relation_name).select{|rel| rel.target_id == subject.id || rel.target == subject}.empty?
|
29
|
+
object.send(self.reverse_relation_class.name.to_relation_name) << self.reverse_relation_class.new(:target => subject)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_rdf(document, subject)
|
34
|
+
subject.send(self.rdf_namespace.camelcase).send(self.rdf_predicate, IqRdf.build_uri(target.origin))
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class Concept::Relation::SKOS::Broader::Base < Concept::Relation::SKOS::Base
|
18
|
+
|
19
|
+
self.rdf_predicate = 'broader'
|
20
|
+
|
21
|
+
def self.narrower_class
|
22
|
+
Concept::Relation::SKOS::Narrower::Base
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.reverse_relation_class
|
26
|
+
self.narrower_class
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.view_section(obj)
|
30
|
+
"main"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.view_section_sort_key(obj)
|
34
|
+
100
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.narrower_editable
|
38
|
+
!singular?
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class Concept::Relation::SKOS::Broader::Mono < Concept::Relation::SKOS::Broader::Base
|
18
|
+
|
19
|
+
def self.partial_name(obj)
|
20
|
+
"partials/concept/relation/skos/broader/mono"
|
21
|
+
end
|
22
|
+
|
23
|
+
# if `singular` is true, only a single occurrence is allowed per instance
|
24
|
+
def self.singular?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2011 innoQ Deutschland GmbH
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
class Concept::Relation::SKOS::Broader::Poly < Concept::Relation::SKOS::Broader::Base
|
18
|
+
|
19
|
+
def self.partial_name(obj)
|
20
|
+
"partials/concept/relation/skos/broader/poly"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|