cancel
Showing results for 
Search instead for 
Did you mean: 

I cannot see metadata values

durdy48
Champ in-the-making
Champ in-the-making
Hi.
Why can i not see metadata values?

When i add a OpenOffice's document with customs metadata defined by user to a space which has a rule with an custom aspects defined in my own model which is this:


<?xml version="1.0" encoding="UTF-8"?>

<model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"              
       xsi:schemaLocation="http://www.alfresco.org/model/dictionary/1.0 ../../../../webapps/alfresco/WEB-INF/classes/alfresco/model/modelSchema.xsd"     
       xmlns="http://www.alfresco.org/model/dictionary/1.0" name="sp:metadatosSP">


   <!– Optional meta-data about the model –>  
   <description>MetadatosSP Model</description>
   <author>William Lesguillier</author>
   <version>1.0</version>

   <imports>
        <!– Import Alfresco Dictionary Definitions –>
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <!– Import Alfresco Content Domain Model Definitions –>
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
   </imports>

   <!– Introduction of new namespaces defined by this model –>
   <namespaces>
      <namespace uri="http://www.juntadeandalucia.es/economiayhacienda/sief/sp" prefix="sp"/>
   </namespaces>

   <aspects>
   
   <!– No utilizar accentos o caracteres especiales en las definiciones –>

      <aspect name="sp:metadatosSP">
         <title>Metadatos SP</title>
      <!–
      <parent>cm:titled</parent>
      –>
         <properties>
            <property name="sp:area">
               <title>Area</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:asunto">
               <title>Asunto</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <!– Se usa el aspecto Author para esta propiedad –>
      <!–
      <property name="sp:autor">
               <title>Autor</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
      –>
            <property name="sp:categoria">
               <title>Categoria</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:comgenerales">
               <title>Comentario</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:dirigidoa">
               <title>Dirigido a</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:dueno">
               <title>Dueno</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:formatodoc">
               <title>Formato</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:idlengua">
               <title>Lenguas</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:idversion">
               <title>Version</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:localizacion">
               <title>Localizacion</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:niveldeseguridad">
               <title>Nivel de Seguridad</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:palabrasclaves">
               <title>Palabras Claves</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:procedede">
               <title>Procede de</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:proyecto">
               <title>Proyecto</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:resumen">
               <title>Resumen</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:so">
               <title>Sistema Operativo</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:softcreacion">
               <title>Software de edicion</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:subarea">
               <title>Sub-area</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:subcategoria">
               <title>Sub-categoria</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:subproyecto">
               <title>Sub-proyecto</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:tipodoc">
               <title>Tipo documento</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <!– Se usa el aspecto Titled para esta propiedad –>
      <!–
            <property name="sp:titulo">
               <title>Tîµµlo</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
      –>
            <property name="sp:verso">
               <title>Version SO</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:versoftcreacion">
               <title>Version soft. de edicion</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:consejeria">
               <title>Consejeria</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:dg">
               <title>Direccion General</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:servicio">
               <title>Servicio</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:revision">
               <title>Revision</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
            <property name="sp:clasificacion">
               <title>Clasificacion</title>
               <type>d:text</type>
               <mandatory>true</mandatory>
            </property>
         </properties>
      <!–
      <mandatory-aspects>
            <aspect>cm:auditable</aspect>
            <aspect>cm:author</aspect>
         </mandatory-aspects>
      –>
      </aspect>

   </aspects>

</model>


I'm following 3 steps:

1. I have in custom-metadata-extractors-context.xml, my own extractor declared:

<bean id="extracter.OpenDocument" class="es.juntadeandalucia.ceh.dgsief.metadata.SPOpenOfficeMetadataExtracter" parent="baseMetadataExtracter" >
        <property name="inheritDefaultMapping">
            <value>true</value>
        </property>
        <property name="mappingProperties">
         <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
             <property name="properties">
                  <props>
                         <prop key="namespace.prefix.sp">http://www.juntadeandalucia.es/economiayhacienda/sief/sp</prop>
                         <prop key="Area">sp:area</prop>
                         <prop key="Asunto">sp:asunto</prop>
                         <prop key="Autor">sp:autor</prop>
                         <prop key="Categoria">sp:categoria</prop>
                         <prop key="ComGenerales">sp:comgenerales</prop>
                         <prop key="DirigidoA">sp:dirigidoa</prop>
                         <prop key="Dueno">sp:dueno</prop>
                         <prop key="FormatoDoc">sp:formatodoc</prop>
                         <prop key="IdLengua">sp:idlengua</prop>
                         <prop key="IdVersion">sp:idversion</prop>
                         <prop key="Localizacion">sp:localizacion</prop>
                         <prop key="NivelDeSeguridad">sp:niveldeseguridad</prop>
                         <prop key="PalabrasClaves">sp:palabrasclaves</prop>
                         <prop key="ProcedeDe">sp:procedede</prop>
                         <prop key="Proyecto">sp:proyecto</prop>
                         <prop key="Resumen">sp:resumen</prop>
                         <prop key="SO">sp:so</prop>
                         <prop key="SoftCreacion">sp:softcreacion</prop>
                         <prop key="SubArea">sp:subarea</prop>
                         <prop key="SubCategoria">sp:subcategoria</prop>
                         <prop key="SubProyecto">sp:subproyecto</prop>
                         <prop key="TipoDoc">sp:tipodoc</prop>
                         <prop key="Titulo">sp:titulo</prop>
                         <prop key="VerSO">sp:verso</prop>
                         <prop key="VerSoftCreacion">sp:versoftcreacion</prop>
                         <prop key="Consejeria">sp:consejeria</prop>
                         <prop key="DG">sp:dg</prop>
                         <prop key="Servicio">sp:servicio</prop>
                         <prop key="Revision">sp:v</prop>
                         <prop key="Clasificacion">sp:clasificacion</prop>
                  </props>
              </property>
          </bean>
      </property>
   </bean>


2. And my bean "SPOpenOfficeMetadataExtracter.java" is like OpenDocumentMetadata.java:




package es.juntadeandalucia.ceh.dgsief.metadata;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.namespace.QName;

import com.catcode.odf.ODFMetaFileAnalyzer;
import com.catcode.odf.OpenDocumentMetadata;


public class SPOpenOfficeMetadataExtracter extends AbstractMappingMetadataExtracter
{
    private static final String KEY_CREATION_DATE = "creationDate";
    private static final String KEY_CREATOR = "creator";
    private static final String KEY_DATE = "date";
    private static final String KEY_DESCRIPTION = "description";
    private static final String KEY_GENERATOR = "generator";
    private static final String KEY_INITIAL_CREATOR = "initialCreator";
    private static final String KEY_KEYWORD = "keyword";
    private static final String KEY_LANGUAGE = "language";
    private static final String KEY_PRINT_DATE = "printDate";
    private static final String KEY_PRINTED_BY = "printedBy";
    private static final String KEY_SUBJECT = "subject";
    private static final String KEY_TITLE = "title";
   
    public static String[] SUPPORTED_MIMETYPES = new String[] {
            MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_GRAPHICS,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_GRAPHICS_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_PRESENTATION_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_SPREADSHEET,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_SPREADSHEET_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_CHART,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_CHART_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_IMAGE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_IMAGE_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_FORMULA,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_FORMULA_TEMPLATE,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT_MASTER,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_TEXT_WEB,
            MimetypeMap.MIMETYPE_OPENDOCUMENT_DATABASE };

    public SPOpenOfficeMetadataExtracter()
    {
        super(new HashSet<String>(Arrays.asList(SUPPORTED_MIMETYPES)));
    }

    @Override
    public Map<String, Serializable> extractRaw(ContentReader reader) throws Throwable
    {
        Map<String, Serializable> rawProperties = newRawMap();
       
        //es.juntadeandalucia.ceh.dgsief.metadata.ODFMetaFileAnalyzer analyzer = new es.juntadeandalucia.ceh.dgsief.metadata.ODFMetaFileAnalyzer();
        ODFMetaFileAnalyzer analyzer = new ODFMetaFileAnalyzer();
        InputStream is = null;
        try
        {
            is = reader.getContentInputStream();
            // stream the document in
            //es.juntadeandalucia.ceh.dgsief.metadata.OpenDocumentMetadata docInfo = analyzer.analyzeZip(is);
            OpenDocumentMetadata docInfo = analyzer.analyzeZip(is);
            if (docInfo != null)
            {
                putRawValue(KEY_CREATION_DATE, docInfo.getCreationDate(), rawProperties);
                putRawValue(KEY_CREATOR, docInfo.getCreator(), rawProperties);
                putRawValue(KEY_DATE, docInfo.getDate(), rawProperties);
                putRawValue(KEY_DESCRIPTION, docInfo.getDescription(), rawProperties);
                putRawValue(KEY_GENERATOR, docInfo.getGenerator(), rawProperties);
                putRawValue(KEY_INITIAL_CREATOR, docInfo.getInitialCreator(), rawProperties);
                putRawValue(KEY_KEYWORD, docInfo.getKeyword(), rawProperties);
                putRawValue(KEY_LANGUAGE, docInfo.getLanguage(), rawProperties);
                putRawValue(KEY_PRINT_DATE, docInfo.getPrintDate(), rawProperties);
                putRawValue(KEY_PRINTED_BY, docInfo.getPrintedBy(), rawProperties);
                putRawValue(KEY_SUBJECT, docInfo.getSubject(), rawProperties);
                putRawValue(KEY_TITLE, docInfo.getTitle(), rawProperties);
               
               
                // Handle user-defined properties dynamically
                Map<String, Set<QName>> mapping = super.getMapping();
                Hashtable userDefinedProperties = docInfo.getUserDefined();
               // Extract those user properties for which there is a mapping
               for (String key : mapping.keySet())
               {
                   if (userDefinedProperties.containsKey(key))
                   {
                       Object value = userDefinedProperties.get(key);
                       if (value != null && value instanceof Serializable)
                       {
                           putRawValue(key, (Serializable) value, rawProperties);
                       }
                   }
               }
            }
        }
        finally
        {
            if (is != null)
            {
                try { is.close(); } catch (IOException e) {}
            }
        }
        // Done
        return rawProperties;
    }
   
}

3.And finally in web-client-config-custom.xml :


<config evaluator="aspect-name" condition="sp:metadatosSP">
      <property-sheet>
         <show-property name="sp:area"/>
         <show-property name="sp:asunto"/> 
         <show-property name="sp:categoria"/>
         <show-property name="sp:comgenerales"/>
         <show-property name="sp:dirigidoa"/>
         <show-property name="sp:dueno"/>
         <show-property name="sp:formatodoc"/>
         <show-property name="sp:idlengua"/>
         <show-property name="sp:idversion"/>
         <show-property name="sp:localizacion"/>
         <show-property name="sp:niveldeseguridad"/>
         <show-property name="sp:palabrasclaves"/>
         <show-property name="sp:procedede"/>
         <show-property name="sp:proyecto"/>
         <show-property name="sp:resumen"/>
         <show-property name="sp:so"/>
         <show-property name="sp:softcreacion"/>
         <show-property name="sp:subarea"/>
         <show-property name="sp:subcategoria"/>
         <show-property name="sp:subproyecto"/>
         <show-property name="sp:tipodoc"/>
         <show-property name="sp:verso"/>
         <show-property name="sp:versoftcreacion"/>
         <show-property name="sp:consejeria"/>
         <show-property name="sp:dg"/>
         <show-property name="sp:servicio"/>
         <show-property name="sp:revision"/>
         <show-property name="sp:clasificacion"/>
      </property-sheet>
   </config>


WHEN I'M DEBUGGING IN ECLIPSE CAN SEEING METADATAS WITH THEIRS VALUES (IN "userDefinedProperties" ) BUT WHEN I'M GOING TO DETAILS VIEW IN WEB INTERFACE ONLY CAN SEEING METADATA LABELS   
DEFINED IN web-client-config-custom.xml AND NOT THEIRS VALUES


THANKS.
11 REPLIES 11

durdy48
Champ in-the-making
Champ in-the-making
It would can be that values doesn't save on database, because i didn't find it.
So, what would be the cause for this?

alf983
Champ in-the-making
Champ in-the-making
Hi,
I have the same problem.
Are you solved?

durdy48
Champ in-the-making
Champ in-the-making
I believe that it exist a bug in alfresco-web-client.jar because i'm debugging source code and i can see that the mapping was doing very good but when it was added the new aspect , this didn't  it .

Could you take a look to source code:

- AddContentDialog
- BaseContentWizard

in package org.alfresco.web.bean.content of alfresco-web-client.jar

the custom metadatas never are added to system alfresco.

Thanks!

alf983
Champ in-the-making
Champ in-the-making
hi durdy,

in the class SPOpenOfficeMetadataExtracter the qname is not declared.
With the method
putRawValue(KEY_CREATOR, docInfo.getCreator(), rawProperties);

the string KEY_CREATOR is a string not a qname.

With the deprecated method "trimPut" with the AbstractMetadataExtracter class you declared the qname and is ok.

How do you now?

durdy48
Champ in-the-making
Champ in-the-making
Hi alf983.

To resolve the problem that i've described i follow the next steps:

1. In SPOpenOfficeMetadataExtracter my code is:

public Map<String, Serializable> extractRaw(ContentReader reader) throws Throwable
    {
        Map<String, Serializable> rawProperties = newRawMap();
       
        //es.juntadeandalucia.ceh.dgsief.metadata.ODFMetaFileAnalyzer analyzer = new es.juntadeandalucia.ceh.dgsief.metadata.ODFMetaFileAnalyzer();
        ODFMetaFileAnalyzer analyzer = new ODFMetaFileAnalyzer();
        InputStream is = null;
        try
        {
            is = reader.getContentInputStream();
            // stream the document in
            //es.juntadeandalucia.ceh.dgsief.metadata.OpenDocumentMetadata docInfo = analyzer.analyzeZip(is);
            OpenDocumentMetadata docInfo = analyzer.analyzeZip(is);
            if (docInfo != null)
            {
                putRawValue(KEY_CREATION_DATE, docInfo.getCreationDate(), rawProperties);
                putRawValue(KEY_CREATOR, docInfo.getCreator(), rawProperties);
                putRawValue(KEY_DATE, docInfo.getDate(), rawProperties);
                putRawValue(KEY_DESCRIPTION, docInfo.getDescription(), rawProperties);
                putRawValue(KEY_GENERATOR, docInfo.getGenerator(), rawProperties);
                putRawValue(KEY_INITIAL_CREATOR, docInfo.getInitialCreator(), rawProperties);
                putRawValue(KEY_KEYWORD, docInfo.getKeyword(), rawProperties);
                putRawValue(KEY_LANGUAGE, docInfo.getLanguage(), rawProperties);
                putRawValue(KEY_PRINT_DATE, docInfo.getPrintDate(), rawProperties);
                putRawValue(KEY_PRINTED_BY, docInfo.getPrintedBy(), rawProperties);
                putRawValue(KEY_SUBJECT, docInfo.getSubject(), rawProperties);
                putRawValue(KEY_TITLE, docInfo.getTitle(), rawProperties);
               
               
                // Handle user-defined properties dynamically
                Map<String, Set<QName>> mapping = super.getMapping();
                Hashtable userDefinedProperties = docInfo.getUserDefined();
               // Extract those user properties for which there is a mapping
               for (String key : mapping.keySet())
               {
                   if (userDefinedProperties.containsKey(key))
                   {
                       Object value = userDefinedProperties.get(key);
                       if (value != null && value instanceof Serializable)
                       {
                           putRawValue(key, (Serializable) value, rawProperties);
                       }
                       if(docInfo.getDescription() == null){
                          docInfo.setDescription("");
                       }
                       docInfo.setDescription(docInfo.getDescription() + ";" + key + ";" + value.toString());
                   }
               }
               putRawValue(KEY_DESCRIPTION, docInfo.getDescription(), rawProperties);
            }
        }
        finally
        {
            if (is != null)
            {
                try { is.close(); } catch (IOException e) {}
            }
        }
        // Done
        return rawProperties;
    }

I introduce all metadatas in "DESCRIPTION" with a character for separation (for example ";") and with a script (of javascript) extract later that metadatas take as reference the separator and insert in their property of my model.
And in my model i have a type with properties that are the metadatas

In the space where i add the documents i have created a rule with two actions: one for specialyse content to my type and two execute a  script which i comment before

i'm Sorry for my bad bad english but i expect help you something

alf983
Champ in-the-making
Champ in-the-making
hi durdy,
is it possible to get a filename that i upload with this class?

durdy48
Champ in-the-making
Champ in-the-making
Hi,
yes, it's possible because one of the field is the filename


Bye

alf983
Champ in-the-making
Champ in-the-making
Which is the field?

durdy48
Champ in-the-making
Champ in-the-making
Hi,

All metadatas are in DESCRIPTION and with javascript you must extract the values because there is a character ";" to separate them.
My javascript file is:

var descripcion = document.properties["cm:description"];

function result()
{  
   if(descripcion == null){
      descripcion = "";
   }
   var array = descripcion.split(";");
   for(i=0;i<array.length;i++){
      if(array[i] == 'Area'){
      document.properties["sp:area"] = array[i+1];
   }else if(array[i] == 'Asunto'){
      document.properties["sp:asunto"] = array[i+1];
   }else if(array[i] == 'Autor'){
      document.properties["sp:autor"] = array[i+1];
   }else if(array[i] == 'Categoria'){
      document.properties["sp:categoria"] = array[i+1];
   }else if(array[i] == 'ComGenerales'){
      document.properties["sp:comgenerales"] = array[i+1];
   }else if(array[i] == 'DirigidoA'){
      document.properties["sp:dirigidoa"] = array[i+1];
   }else if(array[i] == 'Dueno'){
      document.properties["sp:dueno"] = array[i+1];
   }else if(array[i] == 'FormatoDoc'){
      document.properties["sp:formatodoc"] = array[i+1];
   }else if(array[i] == 'IdLengua'){
      document.properties["sp:idversion"] = array[i+1];
   }else if(array[i] == 'IdVersion'){
      document.properties["sp:idversion"] = array[i+1];
   }else if(array[i] == 'Localizacion'){
      document.properties["sp:localizacion"] = array[i+1];
   }else if(array[i] == 'NivelDeSeguridad'){
      document.properties["sp:niveldeseguridad"] = array[i+1];
   }else if(array[i] == 'PalabrasClaves'){
      document.properties["sp:palabrasclaves"] = array[i+1];
   }else if(array[i] == 'ProcedeDe'){
      document.properties["sp:procedede"] = array[i+1];
   }else if(array[i] == 'Proyecto'){
      document.properties["sp:proyecto"] = array[i+1];
   }else if(array[i] == 'Resumen'){
      document.properties["sp:resumen"] = array[i+1];
   }else if(array[i] == 'SO'){
      document.properties["sp:so"] = array[i+1];
   }else if(array[i] == 'SoftCreacion'){
      document.properties["sp:softcreacion"] = array[i+1];
   }else if(array[i] == 'SubArea'){
      document.properties["sp:subarea"] = array[i+1];
   }else if(array[i] == 'SubCategoria'){
      document.properties["sp:subcategoria"] = array[i+1];
   }else if(array[i] == 'SubProyecto'){
      document.properties["sp:subproyecto"] = array[i+1];
   }else if(array[i] == 'TipoDoc'){
      document.properties["sp:tipodoc"] = array[i+1];
   }else if(array[i] == 'Titulo'){
      document.properties["sp:titulo"] = array[i+1];
   }else if(array[i] == 'VerSO'){
      document.properties["sp:verso"] = array[i+1];
   }else if(array[i] == 'VerSoftCreacion'){
      document.properties["sp:versoftcreacion"] = array[i+1];
   }else if(array[i] == 'Consejeria'){
      document.properties["sp:consejeria"] = array[i+1];
   }else if(array[i] == 'DG'){
      document.properties["sp:dg"] = array[i+1];
   }else if(array[i] == 'Servicio'){
      document.properties["sp:servicio"] = array[i+1];
   }else if(array[i] == 'Revision'){
      document.properties["sp:revision"] = array[i+1];
   }else if(array[i] == 'Clasificacion'){
      document.properties["sp:clasificacion"] = array[i+1];
   }else{
      
   }
   }
      document.properties["cm:description"] = '';
   document.save();
}
result();

You must create a rule for execute this script when add a document in a concrete space

Bye