@Override
  public List<OProperty> listProperties(
      OClass oClass, String tab, final DisplayMode mode, final Boolean extended) {
    Collection<OProperty> properties = oClass.properties();
    final String safeTab = tab != null ? tab : DEFAULT_TAB;
    final UIComponentsRegistry registry = OrienteerWebApplication.get().getUIComponentsRegistry();
    Collection<OProperty> filteredProperties =
        Collections2.filter(
            properties,
            new Predicate<OProperty>() {

              @Override
              public boolean apply(OProperty input) {
                String propertyTab = CustomAttributes.TAB.getValue(input);
                boolean ret = safeTab.equals(propertyTab != null ? propertyTab : DEFAULT_TAB);
                if (extended == null) return ret;
                else {
                  CustomAttributes attr =
                      DisplayMode.EDIT.equals(mode)
                          ? CustomAttributes.EDIT_COMPONENT
                          : CustomAttributes.VIEW_COMPONENT;
                  String component = attr.getValue(input);
                  if (component == null) return !extended;
                  return registry.getComponentFactory(mode, input.getType(), component).isExtended()
                      == extended;
                }
              }
            });
    if (filteredProperties == null || filteredProperties.isEmpty()) filteredProperties = properties;
    return ORDER_PROPERTIES_BY_ORDER.sortedCopy(filteredProperties);
  }
 @Override
 public List<OProperty> getDisplayableProperties(OClass oClass) {
   Collection<OProperty> properties = oClass.properties();
   Collection<OProperty> filteredProperties =
       Collections2.filter(properties, PropertyDisplayablePredicate.INSTANCE);
   if (filteredProperties == null || filteredProperties.isEmpty()) filteredProperties = properties;
   return ORDER_PROPERTIES_BY_ORDER.sortedCopy(filteredProperties);
 }
 @Override
 public List<String> listTabs(OClass oClass) {
   Set<String> tabs = new HashSet<String>();
   for (OProperty property : oClass.properties()) {
     String tab = CustomAttributes.TAB.getValue(property);
     if (tab == null) tab = DEFAULT_TAB;
     tabs.add(tab);
   }
   return new ArrayList<String>(tabs);
 }