Wed 23 April 2014

[Smile] Pour sa 3ème édition le CMSday prend une nouvelle envergure

Rendez-vous le Mardi 17 juin 2014 à Paris. Une surface d'exposition doublée, plus de 1 000 visiteurs attendus, 3 nouveaux co-organisateurs, le CMSday sera cette année, le rendez-vous phare de la gestion de contenu open source et des stratégies digitales.

Tue 22 April 2014

[Adacore] Civil Avionics International Forum

Apr 22-23, 2014 – Shanghai, China

AdaCore is a sponsor of this event. 

[Nuxeo Blogs] Brendan Coveney on Content Management and Nuxeo’s Value Proposition

Brendan Coveney - NuxeoAs Nuxeo General Manager for the Americas and APAC, Brendan Coveney knows more than a little about how content management has changed over the years, and how Nuxeo is playing a key role in the new way of supporting content-services in business applications.

We took some time to talk with Coveney and hear his perspective on Nuxeo’s growth and the content management industry overall.

Q: When you first started with Nuxeo (2.5 years ago), what were the typical reasons prospective customers reached out to Nuxeo?

BC: At the time, it was much more content management/document management as an evil – something that had to be done rather than what they wanted to be doing. The impetus in a lot of cases was “we have this amount of content, we need to manage it and it’s going to be crazy.”

Q: Things have changed a lot since that time. What have you seen happen?

BC: We started off with systems of record – essentially the managing of content. Then we moved to systems of engagement – where organizations needed to provide tools that enabled employees and customers to collaborate.

Today, it’s about systems of exploitation. We’ve come to a point where most organizations realize the productivity gains earned by computing and technology over the last twenty years are at a finite limit. We now need to empower workers. Organizations can’t simply computerize and think they’ll gain 20% efficiencies. Modern organizations need to enable their employees to do their jobs properly and become more efficient themselves – that’s where content plays a big role.

In addition, we have seen an enormous amount of data captured by organizations today, as our industry loves making new names, we now call Big Data. We now have systems capable of capturing this data. What is missing are systems that help people make business sense of it all.

In my opinion, content is a realization of this data in human digestible form. So we need systems of handling content which can manage the reports, the business intelligence – in other words, the real jewels of big data.

Q: You’ve said that many organizations come to Nuxeo initially for document management, but leave with the realization that there’s much more to the platform. Can you explain?

BC: A traditional organization would come in for document management. Then they realize that although managing documents is good, they’ve just created another silo. And that’s the last thing a modern organization wants to do.

Today’s organization doesn’t want silos of information, they want everything to be part of a corporate ecosystem. One of the big things they realize when they see the Nuxeo platform is that they can integrate and use all their information in other applications and other ways.

One Nuxeo example is the Navy, where they use content managed in the Nuxeo Platform in 80% of their applications. Nuxeo is a headless backend, where other applications can access information, so they don’t have to develop content services and manage content within the application directly – Nuxeo provides a ready-made content platform. This approach also enables them to take advantage of other information that may not otherwise have been available to them.

Another great example is Leroy Merlin. They built an Employee Intranet on a standard content management system, then expanded with social collaboration. They have one of the highest employee satisfaction rates for any retail organization because they empower employees through information. They provide an environment where employees can easily get the information they need to do their jobs. Traditional retail has been about low cost, but Leroy Merlin is a very advanced organization and they have used this new social intranet to empower their employees. Employees know how to do their job, know what to recommend and have the information needed to upsell themselves. As a result, sales are going up.

Q: When you look at the competitive landscape, who do you see as Nuxeo’s biggest competition? Has this changed much in the last few years?

BC: That’s a great question. Generally, we don’t see a lot of competition from the older legacy content management vendors. What we are seeing more and more, is build-it-ourselves type organizations. These organizations are struggling to see how they can exploit what they have.

There’s no precedence here. There’s no set way of doing things. The traditional approach to building content-based systems was to build it all in-house. Now what we are seeing – thanks to the Nuxeo Platform – is organizations choosing the platform rather than building it all themselves.

The most important thing we do is make organizations aware that the platform is already there, that it’s much quicker and more efficient to use the platform than build and maintain everything on their own.

Q: Organizations come to Nuxeo looking for different capabilities – what are the most common needs they have?

BC: There are two groups primarily. One is the organization who wants to embed the Nuxeo platform – essentially wrapping their own application around Nuxeo (FICO is a good example here). The other, and more growing need, are the customers who use Nuxeo as a standalone platform, as a content-services provider. Other applications connect in and make calls for content through APIs. We’re seeing real growth in this area. A lot of organizations are building applications such as customer information systems and customer interaction systems, whether it’s a financial organization that needs to get brokerage information out to its clients, an energy company who sends out energy bills, or a bank who sends out statements. These organizations use the Nuxeo platform as a place to store, manage and serve this information, and have their customer-facing applications connect in to get it through REST APIs.

It’s really part of the composable enterprise where you have different applications talking via APIs and things are very dynamic.

Q: The industry has evolved from a simple need to manage content, to actually leveraging that content in business applications. When you talk to organizations about their needs, how you get past the “managing” part to actually understanding their full needs?

BC: There are a lot of very bright people out there and when you start talking, the light bulb goes on that it’s not just about managing content, it’s about systems of exploitation. People know there’s something missing, that they are looking for something. And when you show them what the Nuxeo Platform can do, things start to click.

I was showing someone what they could do one and suddenly they said, “Oh, I have three other applications that could use this!” I’d like to say there are some magic words, but it’s simply a matter of explaining what content is and what it can be used for. Once that’s understood, people can see how to use it in their organizations.

People know their business better than we do – that’s a given. What we do is talk about content, then they put it into their context and it becomes clear to them how they can use it.

Q: Is there a set demonstration you show prospective customers?

BC: It’s case by case. We try to figure out what their business needs are. Then typically, we go into a technical presentation where people are looking at a very low level system and they tell you what they need technology-wise. We try to focus on the real business need, more than the technology itself because in most cases there’s a deeper need to understand.

Sometimes they come with a very narrow need and we determine after talking to them that there’s a larger one. We try to talk about that and how Nuxeo can help them. The idea is really trying to understand, not just by hearing the words they say, but really trying to understand what they need.

Q: You say that Nuxeo’s job is to help organizations solve a crisis. Can you explain what you mean?

BC: Many organizations come to us when they have a crisis. Certainly from a business perspective you don’t make sales unless there is a crisis, because there’s no money unless there is one. Think about it, you don’t buy bread unless you need it.

People buy because they have a perceived need. Sometimes that need isn’t apparent to them, in the sense that they are looking for something to manage their content – rather than something they can use to exploit their content to further their business.

Enlightened organizations are now at the stage where they need to exploit content. Business is so competitive, they need to figure out how they remain competitive and, even better, stay ahead of the competition. These organizations realize the best way to do that is to empower their employees and the best way to empower employees is to give them the information they need at the time they need it. It sounds simple, but in my 25 years of IT, I think the hardest thing is to do the simple stuff.

Q: Nuxeo has a unique position in a growing market. What makes Nuxeo unique? How would you characterize Nuxeo’s market?

BC: First of all, we’re not trying to be an application. We’re are not trying to be an end user app, and we don’t try to solve every business need. We understand that we don’t know a customer’s business better than they do, so we provide them with the tools necessary to solve their business needs. We’re not trying to solve that need directly.

Most vendors out there, the traditional enterprise content management vendors, are trying to solve the business need directly. And maybe they solve 60-80% of it through front-facing or cloud based applications. But they don’t solve the system. The people who can solve the system are the people who know the problem best.

Exploiting content is not as simple as building accounting applications. There’s no one standard. If you look at our success stories they range from Jeppesen Boeing managing content for Flight Bags to EA managing binaries. There’s a full range of applications that you would never ever think of. We help companies solve these problems. Rather than develop and manage everything from scratch, we provide organizations with a complete platform that they can not only develop on today, but extend and grow over time.

Q: Why do you market to architects/technical leads?

BC: We focus on architects who have been tasked with solving a problem. Usually they are the ones looking for a solution. There are some architects who think they should develop everything from scratch. Others look around. They might start with that approach, but realize it’s going to take them much longer than they have time for, so they look for solutions that will help them speed up the process to get them on time and on budget. That’s what brings them to Nuxeo – there aren’t many platform providers out there like Nuxeo.

Final Take: What Nuxeo Brings to Content Management

It’s clear when talking to Brendan that the organization’s need for content management has grown up. We are moving away from monolithic document management systems that required extensive training and administration to solutions that provide content within the context of business processes.

There has been a big shift in user experience overall and the easier a system is to use, the more efficient the worker becomes. This is the same for content management. Content is no longer limited to a file or a document, much of it is managed through online forms, and today’s content management systems need to provide the structures and workflows to process this content efficiently and distribute to those that need it.

The post Brendan Coveney on Content Management and Nuxeo’s Value Proposition appeared first on Nuxeo Blogs.

[Logilab] Pylint 1.2 released!

Once again, a lot of work has been achieved since the latest 1.1 release. Claudiu, who joined the maintainer team (Torsten and I) achieved a great work in the past few months. Also lately Torsten has backported a lot of things from their internal G[oogle]Pylint. Last but not least, various people contributed by reporting issues and proposing pull requests. So thanks to everybody!

Notice Pylint 1.2 depends on astroid 1.1 which has been released at the same time. Currently, code is available on Pypi, and Debian/Ubuntu packages should be ready shortly on Logilab's acceptance repositories.

Below is the changes summary, check the changelog for more info.

New and improved checks:

  • New message 'eval-used' checking that the builtin function eval was used.
  • New message 'bad-reversed-sequence' checking that the reversed builtin receive a sequence (i.e. something that implements __getitem__ and __len__, without being a dict or a dict subclass) or an instance which implements __reversed__.
  • New message 'bad-exception-context' checking that raise ... from ... uses a proper exception context (None or an exception).
  • New message 'abstract-class-instantiated' warning when abstract classes created with abc module and with abstract methods are instantied.
  • New messages checking for proper class __slots__: 'invalid-slots-object' and 'invalid-slots'.
  • New message 'undefined-all-variable' if a package's __all__ variable contains a missing submodule (#126).
  • New option logging-modules giving the list of module names that can be checked for 'logging-not-lazy'.
  • New option include-naming-hint to show a naming hint for invalid name (#138).
  • Mark file as a bad function when using python2 (#8).
  • Add support for enforcing multiple, but consistent name styles for different name types inside a single module.
  • Warn about empty docstrings on overridden methods.
  • Inspect arguments given to constructor calls, and emit relevant warnings.
  • Extend the number of cases in which logging calls are detected (#182).
  • Enhance the check for 'used-before-assignment' to look for nonlocal uses.
  • Improve cyclic import detection in the case of packages.

Bug fixes:

  • Do not warn about 'return-arg-in-generator' in Python 3.3+.
  • Do not warn about 'abstract-method' when the abstract method is implemented through assignment (#155).
  • Do not register most of the 'newstyle' checker warnings with python >= 3.
  • Fix 'unused-import' false positive with augment assignment (#78).
  • Fix 'access-member-before-definition' false negative with augment assign (#164).
  • Do not crash when looking for 'used-before-assignment' in context manager assignments (#128).
  • Do not attempt to analyze non python file, eg '.so' file (#122).
  • Pass the current python path to pylint process when invoked via epylint (#133).

Command line:

  • Add -i / --include-ids and -s / --symbols back as completely ignored options (#180).
  • Ensure init-hooks is evaluated before other options, notably load-plugins (#166).


  • Improve pragma handling to not detect 'pylint:*' strings in non-comments (#79).
  • Do not crash with UnknownMessage if an unknown message identifier/name appears in disable or enable in the configuration (#170).
  • Search for rc file in ~/.config/pylintrc if ~/.pylintrc doesn't exists (#121).
  • Python 2.5 support restored (#50 and #62).


  • Python 3.4 support
  • Enhanced support for metaclass
  • Enhanced namedtuple support

Nice easter egg, no?

[Adacore] gnat2xml generates representation clauses

gnat2xml has a new switch --rep-clauses that causes it to generate representation clauses for certain types. Size and Component_Size clauses, as well as record_representation_clauses, are generated as appropriate. These may be used to see the representation the compiler has chosen.

[Adacore] Secondary stack reclamation during elaboration

The compiler now reclaims the storage used by the secondary stack during the elaboration of a library level object declaration when the initialization expression contains a function returning a controlled or unconstrained result.

Sat 19 April 2014

[Adacore] New gprinstall option to copy only project sources

Using gprinstall's --sources-only option it is now possible to install projects sources only. In this mode it is not required for the project to have been built before.

Fri 18 April 2014

[Logilab] Ecriture de liaisons C++ pour Python

Dans le cadre des travaux d'interfaçage de l'application Code_TYMPAN avec du code Python, nous avons réalisé l'étude ci-dessous sur les différents moyens de générer des liaisons Python pour du code C++. Cette étude n'a pas vocation d'être exhaustive et s'est concentrée sur les aspects qui nous intéressaient directement pour les travaux susmentionnés.

Solutions existantes

Une recherche des solutions existantes a été effectuée, qui a permis d'obtenir la liste suivante pour une écriture manuelle du code d'interfaçage :

  • Cython, un langage de programmation inspiré de Python, basé sur Pyrex
  • Boost.Python, une librairie C++ de la collection Boost permettant d'écrire des liaisons Python
  • PyBindGen, un outil implémenté en Python et permettant de décrire des liaisons C++ directement dans ce langage
  • Swig, un outil permettant de générer des liaisons C++ pour plusieurs langages de programmation
  • Shiboken, un générateur de code d'enrobage pour des bibliothèques C/C++ basé sur du CPython

Des solutions existent pour automatiser cette écriture. Ce sont des outils qui se basent sur des compilateurs (gcc, clang) pour faire l'analyse grammaticale du code C++ et générer le code d'interfaçage correspondant. Par exemple :

  • XDress, qui permet de générer des fichiers Cython (.pyx, .pxd) à partir de gcc-xml ou de libclang
  • PyBindGen dispose de fonctionnalités permettant de générer des liaisons python à partir de gcc
  • Ce billet explique comment utiliser libclang pour parcourir l'AST d'un code C++ et générer des liaisons Boost.Python

Aspects pris en compte

Cet article est intéressant car il aborde de façon très complète les problématiques découlant de l'écriture de liaisons C++ pour des langages de haut niveau. Il a été écrit lors des travaux de développement de Shiboken.

Dans notre cas, les critères pour le choix d'une solution finale portaient sur différents aspects :

  • Le coût de développement : prise en main de l'outil, quantité de code à écrire pour enrober une classe C++ donnée, coût de l'intégration dans le système de build, degré d'automatisation de la solution, lisibilité du code généré, etc.
  • La gestion de la mémoire : comptage de référence, gestion de la propriété des objets
  • La qualité et l'exhaustivité du support C++ : compatibilité STL, gestion des références et pointeurs, des templates, surcharges d'opérateurs, etc.
  • La pérennité de la solution : technologies mises en œuvre par l'outil, qualité de la documentation, support, taille et degré d'activité de la communauté de développeurs

Solutions envisagées

Swig n'a pas été retenu partant de l'a priori que c'était une solution plutôt lourde et davantage orientée C que C++, constat tiré lors de travaux réalisés par Logilab il y a quelques mois de cela. La solution Boost.Python n'a pas été explorée car notre souhait était de nous rapprocher davantage du Python que du C++. Shiboken semble prometteur, bien que peu documenté et mal référencé (les premières recherches tombent sur d'anciennes pages du projet, donnant l'impression que la dernière release date d'il y a plusieurs années, alors qu'en fait, non). Il a été écarté par manque de temps.

PyBindGen et Cython ont fait l'objet de tests.

La cible des tests a été l'interfaçage de smart pointers, puisque cela correspond à un de nos besoins sur le projet Code_TYMPAN.

Les essais ont été réalisés sur des classes simplifiées:

  • MyElement, classe qui représente un élément à encapsuler dans un smart pointer et hérite de IRefCount qui implémente un comptage de référence
  • SmartPtr, classe smart pointer "maison" de l'application
  • Quelques fonctions de test manipulant des smart pointers SmartPtr

Voici un extrait des en-têtes du code C++:

#ifndef MY_ELEMENT_H
#define MY_ELEMENT_H
#include <iostream>
using namespace std;
#include "SmartPtr.h"

class MyElement : public IRefCount
        MyElement ();
        MyElement (string);
            string Name(){ return _name; }
            virtual ~MyElement ();

        string _name;
typedef SmartPtr<MyElement> SPMyElement;

#ifndef SMART_PTR_H
#define SMART_PTR_H
template <class T> class SmartPtr
        const T* getRealPointer() const;

        T* _pObj;

SPMyElement BuildElement();
void UseElement(SPMyElement elt);


Cet outil offre maintenant un bon support du C++ (globalement depuis la version 0.17). Son avantage est qu'il permet la manipulation d'objets à la fois C++ et Python dans des fichiers Cython.

  • Écriture (facultative) d'un fichier .pxd qui contient une recopie des headers à enrober (avec un lien vers les fichiers): déclarations des types, classes, fonctions...
  • Écriture d'un fichier .pyx qui contient des appels de fonctions, constructions d'objets C ou python. Les fonctions et classes de ce module sont utilisables depuis un script Python
  • Compilation du code Cython décrivant les interfaçages C++, génération et compilation du code C++ correspondant et production d'une librairie Python.

Cython offre un support pour les conteneurs de la STL, les templates, la surcharge de la plupart des opérateurs ("->" non supporté), le passage d'arguments par référence et par pointeur, etc.

Actuellement en version 0.20.1, la dernière release date du 11 février 2014. Les outils Cython sont relativement bien documentés et sa communauté de développeurs est active.


Voici le code d'interfaçage Cython correspondant à l'exemple exposé ci-dessus:

from distutils.core import setup
from Cython.Build import cythonize



from libcpp.string cimport string

cdef extern from "src/SmartPtr.h":
    cdef cppclass SmartPtr[T]:
        SmartPtr(T *)
        T *getRealPointer() # Pas de surcharge de ->. L'accès à l'objet ne peut être qu'explicite

cdef extern from "src/MyElement.h":
    cdef cppclass MyElement:
        string Name()

cdef extern from "src/Test.h":
    SmartPtr[MyElement] BuildSPElement()
    void UseSPElement(SmartPtr[MyElement])


# distutils: language = c++
# distutils: libraries = element

cimport smartptr
cimport cython

cdef class PySPMyElement:
    cdef SmartPtr[MyElement] thisptr

    def __cinit__(self, name=""):
        """ PySPMyElement constructor """
        if name == "":
            self.thisptr = SmartPtr[MyElement](new MyElement())
            self.thisptr = SmartPtr[MyElement](new MyElement(name))

    def get_name(self):
        """ Returns the name of the element """
        return self.thisptr.getRealPointer().Name()

def build_sp_elt():
    """ Calls the C++ API to build an element """
    elt = PySPMyElement.__new__(PySPMyElement)
    elt.thisptr = BuildSPElement()
    return elt

def use_sp_elt(elt):
    """ Lends elt to the C++ API """


XDress est un générateur automatique de code d'interfaçage C/C++ écrit en Python, basé sur Cython.

  • On liste dans un fichier les classes et fonctions à envelopper (il n'est pas nécessaire de mettre la signature, le nom suffit. On peut choisir d'envelopper seulement certaines classes d'un .h).
  • On exécute xdress qui génère les .pyx et .pxd correspondants

XDress permet d'envelopper des conteneurs STL via son générateur stlwrap (les conteneurs à enrober doivent être listés dans le A titre d'exemple, les vecteurs sont convertis en numpy array du type contenu.

Ce projet est récent et pas très documenté, mais il semble prometteur.


  • Écriture d'un script Python qui décrit les classes/fonctions C++ à enrober en s'appuyant sur le module PyBindGen (1) → permet de générer un fichier .cpp
  • Compilation du code C++ généré, avec la librairie du programme à envelopper et génération d'une librairie Python.

Ce processus peut être automatisé:

  • Écriture d'un script Python qui utilise les outils PyBindGen pour lister les modules (headers) à envelopper, les lire et lancer la génération automatique des liaisons c++


  • Écriture d'un script Python qui utilise les outils PyBindGen pour lister les modules (headers) à envelopper et générer le script Python décrit en (1) (ce qui permettrait une étape intermédiaire pour personnaliser les liaisons)

PyBindGen offre un support pour la STL, l'héritage (multiple), la gestion des exceptions C++ côté Python, la surcharge d'opérateurs, le comptage de référence, la gestion de la propriété des objets. Mais il supporte mal les templates.

Actuellement en version 0.17, la dernière release date du 15 février 2014 (entre autres ajout de la compatibilité Python 3.3).


PyBindGen, en l'état, n'offre pas la possibilité d'envelopper simplement des templates, ni des smart pointers "maison" par extension.

Une classe de ce package permet d'envelopper des shared pointers de Boost (boost::shared_ptr). Il serait à priori possible de la modifier légèrement pour enrober les smart pointers de l'application Code_TYMPAN (non testé).

Voici néanmoins à titre d'exemple le code permettant d'envelopper la classe MyElement et des fonctions manipulant non plus des smart pointers mais des 'MyElement *'

Test.h :

MyElement *BuildElement();
void UseElement(MyElement *elt); :

import pybindgen
import sys
from pybindgen import retval
from pybindgen import param

mod = pybindgen.Module('smartptr')

# File includes

# Class MyElement
MyElement = mod.add_class('MyElement')
MyElement.add_method('Name', retval('std::string'), [])

# Test functions
# transfer_ownership=False : here Python program keeps the ownership of the element it passes to the C++ API
mod.add_function('UseElement', None, [param('MyElement *', 'elt', transfer_ownership=False)])
# caller_owns_return=True : here Python program will be responsible for destructing the element returned by BuildElement
mod.add_function('BuildElement', retval('MyElement *',  caller_owns_return=True), [])

if __name__ == '__main__':


Les liaisons Python s'écrivent directement en C++.

C'est un outil très fiable et pérenne, avec de par sa nature un très bon support C++ : gestion de la mémoire, templates, surcharges d'opérateurs, comptage de référence, smart pointers, héritage, etc.

Inconvénient : la syntaxe (en mode templates C++) n'est pas très intuitive.


Les solutions Cython et PyBindGen ont été explorées autour de la problématique d'enrobage de smart pointers. Il en est ressorti que:

  • Il est possible d'enrober facilement des smart pointers Code_TYMPAN en Cython. L'approche qui a été choisie est de manipuler depuis Python les objets C++ directement au travers de smart pointers (les objets Python contenus dans le .pyx encapsulent des objets SmartPtr[T *], agissant donc comme des proxys vers les objets). De cette façon, l'utilisation depuis Python d'un objet C++ incrémente le compteur de référence côté C++ et cela garantit qu'on ne perdra pas la référence à un objet au cours de son utilisation côté Python. Un appel à getRealPointer() pour enrober des fonctions manipulant directement des T * sera toujours possible dans le code Cython au besoin.
  • PyBindGen présente l'intérêt d'offrir des moyens de gérer l'attribution de la propriété des éléments entre C++ et Python (transfer_ownership, caller_owns_return). Malheureusement, il n'offre pas la possibilité d'enrober des smart pointers sans modification de classes PyBindGen, ni d'envelopper des templates.

Par ailleurs, après utilisation de PyBindGen, il nous a semblé que bien qu'il présente des idées intéressantes, sa documentation, ses tutoriels et son support sont trop succints. Le projet est développé par une seule personne et sa viabilité est difficile à déterminer. Cython en revanche offre un meilleur support et plus de fiabilité.

Le choix final s'est donc porté sur Cython. Il a été motivé par un souci d'utiliser un outil fiable limitant les coûts de développement (élimination de PyBindGen), aussi proche de Python que possible (élimination de Boost.Python). Cet outil semble fournir un support C++ suffisant par rapport à nos besoins tels que perçus à ce stade du projet.

Si on venait à nécessiter un moyen de générer automatiquement les liaisons python, XDress présente l'avantage de permettre l'utilisation de libclang comme alternative à gcc-xml (PyBindGen est basé sur gcc-xml uniquement). Une possibilité serait par ailleurs d'utiliser XDress pour générer uniquement le .pxd et d'écrire le .pyx manuellement.

Une question qui n'a pas été abordée au cours de cette étude car elle ne correspondait pas à un besoin interne, mais qui est néanmoins intéressante est la suivante: est-il possible de dériver depuis Python des classes de base définies en C++ et enveloppées en Cython, et d'utiliser les objets résultants dans l'application C++ ?

[Nuxeo Blogs] A Spreadsheet Editor for Lists of Documents in the Nuxeo Platform

The Nuxeo roadmap put a lot of emphasis on working with large collections of assets or documents, leading to the new collections module, as well as some upcoming updates around the user experience when selecting values in a content view.

One particular item of the roadmap focuses on the ability to edit data in your repository as if you were in a spreadsheet-like grid. Indeed, spreadsheet copy-paste by dragging the cell’s value is something very intuitive and very productive for handling bulk-editing of thousands of documents. We want to somehow emulate this behavior. One of the challenges is that when you handle documents in a repository, you have to respect some constraints:

  • Some metadata is mandatory,
  • Some have constrained values among a controlled list, that store the id value while it displays the label,
  • You may even have more complex validation logic,
  • Sometimes some information is read-only, you don’t want to let the user modify it,
  • This is not a constraint, but a must: you want to be able to use Nuxeo Studio for configuring the spreadsheet instance, mapping that configuration to the notion of result layout.

You need to make sure your user interface will be able to enforce all those constraints. There are two ways to implement a spreadsheet editor:

  1.  Produce a clean Excel/Open Office /CSV export of the data, let the user do their modification in the desktop application, then re-import the new table updating the related documents in the repository.
  2. Have a built-in table-like solution, that will emulate the user interface of Excel, to edit the data.

I have a reported implementation of method 1 by one of our customers. They used the XML Excel format for producing a file that has some locked cells, controlled lists, etc … The production of the file is based on rendering logic that injects values in the initial template. They reported having issues making sure the Excel file was okay, with the correct protection of cells, etc … But, this is still doable, with some limitations on the kind of controls that can be presented to the user.

Another approach still based on exporting an Excel file could be to use advanced templates based on JXLS library. I am pretty sure we could produce an interesting template, here also with some limitations to the kind of widgets available for editing the data.

For method 2, I found a library that could be the basis of our future implementation of handsontable.js. This awesome library implements the spreadsheet user experience in a JavaScript grid and provides all the plugability you would expect from such a component.

I have played with it a little bit using the nuxeo.js JavaScript client - the result is on github (pardon my JavaScript ;)) and I did a short video to share the result:

In short, what the library allows you to do is:

  • Define the datasource that you map to a Nuxeo query (preferably using the PageProvider operation, that allows you to control the max result). It is possible to have advanced mappings (subfields to column).
  • Define the columns that should be displayed.
  • Define their type, the renderer to use for presenting the value, as well as the editor for editing. You can write your own renderers and editors. For instance, I have adapted and integrated a select2 editor (that was implemented by someone else and found on github). This means we can theoretically map all of our widget library.
  • Define which columns are editable or not.
  • Define formatters, so as to control the police, the size and the colors of the cell depending on some business rules, as well as if it should be displayed as numbers, etc…
  • Benefit from the undo/redo user experience.
  • Provide built-in search filtering capabilities.
  • Register to any of the events that happen on the table, to have a tight link of your backed model to what the user does on the table.

What we should do to integrate it nicely into the Nuxeo Platform:

  • Integrate the table to content views. It could be either another result layout (like the lightbox one is going to be) or just a new button on the content views template that displays it in a pop up.
  • Plug the data of the Handsontable to the state of the content view: user filters data on the content view, then extracts the result into the JavaScript grid to edit it.
  • Implement a homogeneous set of editors and renderers mapped to the main widgets of our layout library.
  • Plug the Handsontable instantiation definition to the layout service so as to be able to configure it from Studio.
  • Implement pagination logic for fetching larger sets of data.
  • Implement a robust bulk-save of the rows updates (currently, I call the REST API row by row, which actually happens to give a very good results already).

As you can see, this is a full time job, but this first integration attempt is already promising! If you are curious for some more “hands-on” details, here are some of the interesting parts. I use the Nuxeo JavaScript client, so I need to instantiate it:

<br />var connectInfo = {<br />baseURL: "",<br />username: "Administrator",<br />password: "Administrator",<br />timeout: 300000,<br />schemas: "dublincore"<br />};<br />var client = new nuxeo.Client(connectInfo);<br />

I start by fetching the data (the whole code is wrapped in a function with queryString param, so as to easily instantiate the table with query based content. Note the use of Document.PageProvider, as it is paginated, versus Document.Query, which would not scale for a large repository:

&lt;<br />client.operation('Document.PageProvider') .params({ query: queryString, maxResults:"500", pageSize:"500" }) .execute (…)<br /><br />

Then in the call back function of the execute method, I instantiate the Handsontable:

<br />$("#example2").handsontable(handsonOptions); // #example2 is a div in the page, handsonOptions is an array with the options.<br />

The main options I use are:

data: the data to be injected in the table, it is the direct data result of the Document.PageProvider operation

columns: an array of the definition of the columns type. Ex:

<br />columns: [ {<br />data: "properties.dc:title",<br />readOnly: true,<br />renderer: orangeRenderer<br />},<br />

or a more advanced one that leverages the select2 editor:

<br />{<br />data: "properties.ipr:media_type",<br />editor: "select2",<br />select2Options: { // these options are the select2 initialization options<br />formatResult: getDefaultLabel,<br />query: function (query) {<br />getVocabularyData("dam_media_type", function (data) {<br />var results = [];<br />query.callback({<br />results: data<br />});<br />});<br />},<br />dropdownAutoWidth: true,<br />allowClear: true,<br />width: "resolve"<br />}<br />}<br />

You may notice the “data” mapping, with the json properties traversal. For select2, I use the automation API to fetch the values. Actually I have the same one for the JSF implementation of the suggest widget.

<br />function getVocabularyData(directoryName, callback) {<br />client.operation("Directory.SuggestEntries").params({<br />"directoryName": directoryName,<br />"localize":true,<br />"lang”:"en"<br />}).execute(function (error, data) {<br />callback(data)<br />});<br />}<br />

I also added an “afterChange” callback:

afterChange: function (change, source) {<br />if (change != null) {<br />for (var i = 0; i &lt; change.length; i++) {<br />listToUpdate[(myData[change[i][0]].uid)] = myData[change[i][0]];<br />}<br />ht.render();<br />}<br />}<br />

This allows me to store modified cells so I can save them for later and change the colors of the cells that have been updated, letting the user know what is going to be changed.

You should have a deeper look at the Handsontable documentation for discovering all that can be done. You can also refer to the Nuxeo JavaScript client documentation to understand how to add more interactions with the repository. Do not hesitate to share your experiences here!

The post A Spreadsheet Editor for Lists of Documents in the Nuxeo Platform appeared first on Nuxeo Blogs.

[Adacore] Implement workaround for FPU store errata on LEON3

The compiler switch -mfix-ut699 has been enhanced to work around the store forwarding problem of the FPU in Aeroflex Gaisler's LEON3 Microprocessor.

[Adacore] Better provability of checks on floats

GNATprove now analyzes type bounds of sub-expressions to compute when an overflow check or a range check cannot fail, because these bounds guarantee that the resulting bounds on the result fit into the required range. As a result, many run-time checks on floats that were previously not proved become proved.