class MetaDataInfoBuilder {

    public MetaDataInfo buildMetaDataInfo(GeoPackageFeatureLayer featureLayer)
    {
        DefaultMetaDataInfo metaInfo = null;

        List<Map<String, Serializable>> data = featureLayer.getData();
        String timeColumn = null;
        if (!data.isEmpty())
        {
            Map<String, Class<?>> columnsToTypes = New.map();

            int index = 0;
            for (Map<String, Serializable> row : data)
            {
                for (Entry<String, Serializable> entry : row.entrySet())
                {
                    timeColumn = findTimeColumn(timeColumn, entry);

                    if (!columnsToTypes.containsKey(entry.getKey()) && entry.getValue() != null)
                    {
                        columnsToTypes.put(entry.getKey(), entry.getValue().getClass());
                    }
                }

                if (columnsToTypes.size() >= row.size())
                {
                    break;
                }

                index++;

                if (index == data.size())
                {
                    for (Entry<String, Serializable> entry : row.entrySet())
                    {
                        if (!columnsToTypes.containsKey(entry.getKey()))
                        {
                            columnsToTypes.put(entry.getKey(), Serializable.class);
                        }
                    }
                }
            }

            metaInfo = new DefaultMetaDataInfo();

            columnsToTypes.put(GeoPackageColumns.GEOMETRY_COLUMN, Geometry.class);

            for (Entry<String, Class<?>> entry : columnsToTypes.entrySet())
            {
                metaInfo.addKey(entry.getKey(), entry.getValue(), this);
            }

            metaInfo.setGeometryColumn(GeoPackageColumns.GEOMETRY_COLUMN);
            if (timeColumn != null)
            {
                metaInfo.setSpecialKey(timeColumn, TimeKey.DEFAULT, this);
            }
        }

        return metaInfo;
    }

}