---
title: Catalog
page_mask: usermanual-pdf-exclude
page_mask: started-pdf-exclude
---
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <title>Brooklyn Entity - Brooklyn Node</title>
  <meta name="fragment" content="!">

  {% include head.html %}
  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"/>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
  <link rel="stylesheet" href="{{site.path.style}}/css/catalog_items.css" type="text/css" media="screen"/>
</head>
<body>
{% include header.html %}
<div id="container">
  <div id="summary"></div>

  <ul class="nav nav-tabs">
    <li class="active"><a href="#configKeys" data-toggle="tab">Config Keys</a></li>
    <li id="sensorsTab"><a href="#sensors" data-toggle="tab">Sensors</a></li>
    <li id="effectorsTab"><a href="#effectors" data-toggle="tab">Effectors</a></li>
  </ul>

  <div class="tab-content">
    <div class="tab-pane active" id="configKeys"></div>
    <div class="tab-pane" id="sensors"></div>
    <div class="tab-pane" id="effectors"></div>
  </div>
</div>

<script src="{{site.path.style}}/js/underscore-min.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="{{site.path.style}}/js/catalog/common.js" type="text/javascript"></script>
<script src="{{site.path.style}}/js/catalog/items.js" type="text/javascript"></script>

<script type="text/javascript">
  $(document).ready(function () {
    $(window).on('hashchange', updateItem);

    updateItem(items);

    function updateItem(items) {
      var args, catalog_type;
      args = getArgs();
      if(args.length!=2) {
        alert('bad entity format')
        return;
      }

      // e.g. entities/org.apache.brooklyn.entity.brooklynnode.BrooklynNode
      if (!brooklyn) return;
      var item = brooklyn.findItemOfType(items[args[0]], args[1]);

      $("#summary").html(brooklyn.typeSummary(item));
      if(args[0] == 'entities') {
        catalog_type = 'Entity';
      } else if(args[0] == 'policies') {
        catalog_type = 'Policy';
      } else if(args[0] == 'locations') {
        catalog_type = 'Location'
      }

      document.title = 'Brooklyn ' + catalog_type + ' - ' + item.name;

      item.config.forEach(function (element) {
        $("#configKeys").append(brooklyn.configKeyCard(element));
      });

      if(args[0] == 'entities') {
        $("#sensorsTab").show();
        $("#effectorsTab").show();
        item.sensors.forEach(function (element) {
          $("#sensors").append(brooklyn.sensorCard(element));
        });
        if (item.effectors != undefined) {
          item.effectors.forEach(function (element) {
            $("#effectors").append(brooklyn.effectorCard(element));
          });
        }
        
      } else {
        $("#sensorsTab").hide();
        $("#effectorsTab").hide();
      }
    }

    function getArgs() {
      var args;
      var params = window.location.hash;
      if(params) {
        if(params.length <= 2) {
          alert('No such catalog item');
        }
        args = params.substring(2).split('/');
      } else {
        params = getParameterByName('_escaped_fragment_');
        args = params.split('/');
      }

      return args;

      function getParameterByName(name) {
        var search = window.location.search || document.location.search;
        if(search === undefined) {
          alert('No get parameter specified for a catalog item')
        }

        name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
        var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
                results = regex.exec(search);
        return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
      }
    }
  });
</script>
</body>
</html>
