diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/AbstractEntityAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/AbstractEntityAdaptor.java
index c582d20c3b8f8b0d8443a9937f50da3e7ee71771..c2809d864eb76586c92fbea45453fd7fdce27b0d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/AbstractEntityAdaptor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/AbstractEntityAdaptor.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IEntityPropertiesHolder;
 import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE;
 
@@ -45,32 +46,33 @@ public class AbstractEntityAdaptor implements IEntityAdaptor
     {
         for (EntityPropertyPE property : propertiesHolder.getProperties())
         {
-            if (property.getEntityTypePropertyType().isDynamic())
-            {
-                // values of dynamic properties can't be referred to - it wouldn't be deterministic
-                continue;
-            }
-            final PropertyTypePE propertyType =
-                    property.getEntityTypePropertyType().getPropertyType();
+            EntityTypePropertyTypePE etpt = property.getEntityTypePropertyType();
+            final PropertyTypePE propertyType = etpt.getPropertyType();
             final String propertyTypeCode = propertyType.getCode();
-            final String value;
-            if (property.getMaterialValue() != null)
-            {
-                value = property.getMaterialValue().getCode();
-            } else if (property.getVocabularyTerm() != null)
-            {
-                value = property.getVocabularyTerm().getCode();
-            } else
-            {
-                value = property.getValue();
-            }
-            if (propertyType.getTransformation() == null)
+            if (etpt.isDynamic())
             {
-                addProperty(new BasicPropertyAdaptor(propertyTypeCode, value, property));
+                addProperty(new DynamicPropertyAdaptor(propertyTypeCode, this, property));
             } else
             {
-                addProperty(new XmlPropertyAdaptor(propertyTypeCode, value, property,
-                        propertyType.getTransformation()));
+                final String value;
+                if (property.getMaterialValue() != null)
+                {
+                    value = property.getMaterialValue().getCode();
+                } else if (property.getVocabularyTerm() != null)
+                {
+                    value = property.getVocabularyTerm().getCode();
+                } else
+                {
+                    value = property.getValue();
+                }
+                if (propertyType.getTransformation() == null)
+                {
+                    addProperty(new BasicPropertyAdaptor(propertyTypeCode, value, property));
+                } else
+                {
+                    addProperty(new XmlPropertyAdaptor(propertyTypeCode, value, property,
+                            propertyType.getTransformation()));
+                }
             }
         }
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/DynamicPropertyAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/DynamicPropertyAdaptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..73f22ff36c3fe5aff19a6740fad822fba8c08a15
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/DynamicPropertyAdaptor.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed 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.
+ */
+
+package ch.systemsx.cisd.openbis.generic.server.dataaccess.db.dynamic_property.calculator;
+
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IPropertyValueValidator;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.PropertyValidator;
+import ch.systemsx.cisd.openbis.generic.shared.basic.BasicConstant;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE;
+
+/**
+ * {@link IEntityPropertyAdaptor} for dynamic property with lazy evaluation and cyclic dependencies
+ * detection.
+ * 
+ * @author Piotr Buczek
+ */
+// TODO 2010-11-05, Piotr Buczek: refactor to use DynamicPropertyEvaluator
+class DynamicPropertyAdaptor implements IEntityPropertyAdaptor
+{
+    private enum State
+    {
+        EMPTY, EVALUATING, EVALUATED
+    }
+
+    private static final IPropertyValueValidator validator = new PropertyValidator();
+
+    private static final String ERROR_PREFIX = "ERROR: ";
+
+    private State state = State.EMPTY;
+
+    private String value = null;
+
+    private final String code;
+
+    private final EntityPropertyPE propertyPE;
+
+    private final IEntityAdaptor entityAdaptor;
+
+    public DynamicPropertyAdaptor(String code, IEntityAdaptor entityAdaptor,
+            EntityPropertyPE propertyPE)
+    {
+        this.code = code;
+        this.entityAdaptor = entityAdaptor;
+        this.propertyPE = propertyPE;
+    }
+
+    public String propertyTypeCode()
+    {
+        return code;
+    }
+
+    private String doGetValue()
+    {
+        switch (state)
+        {
+            case EMPTY:
+                // start evaluation
+                state = State.EVALUATING;
+                value = doEvaluate();
+                break;
+            case EVALUATING:
+                // cycle found - return an error
+                state = State.EVALUATED;
+                String errorMsg =
+                        ERROR_PREFIX + "cycle found in dependencies of property "
+                                + propertyTypeCode();
+                value = BasicConstant.ERROR_PROPERTY_PREFIX + errorMsg;
+                break;
+            case EVALUATED:
+                // value was already computed
+                break;
+        }
+        return value;
+    }
+
+    private String doEvaluate()
+    {
+        EntityTypePropertyTypePE etpt = propertyPE.getEntityTypePropertyType();
+        assert etpt != null;
+        try
+        {
+            // TODO 2010-11-05, Piotr Buczek: use cache
+            final DynamicPropertyCalculator calculator =
+                    DynamicPropertyCalculator.create(etpt.getScript().getScript());
+            calculator.setEntity(entityAdaptor);
+            final String dynamicValue = calculator.evalAsString();
+            final String validatedValue =
+                    validator.validatePropertyValue(etpt.getPropertyType(), dynamicValue);
+            return validatedValue;
+        } catch (Exception e)
+        {
+            String errorMsg = ERROR_PREFIX + e.getMessage();
+            // operationLog.info(errorMsg);
+            return BasicConstant.ERROR_PROPERTY_PREFIX + errorMsg;
+        }
+    }
+
+    public String valueAsString()
+    {
+        return doGetValue();
+    }
+
+    public String renderedValue()
+    {
+        return valueAsString();
+    }
+
+    public EntityPropertyPE getPropertyPE()
+    {
+        return propertyPE;
+    }
+
+    //
+    // Object
+    //
+
+    @Override
+    public String toString()
+    {
+        return propertyTypeCode() + " " + valueAsString();
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/XmlPropertyAdaptor.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/XmlPropertyAdaptor.java
index 48d62b804197730da8bc342345a724887aa7ae24..6862cd715b7eabe32fc3e94d19dae614205dcf90 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/XmlPropertyAdaptor.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/dynamic_property/calculator/XmlPropertyAdaptor.java
@@ -20,7 +20,8 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE;
 import ch.systemsx.cisd.openbis.generic.shared.util.XmlUtils;
 
 /**
- * {@link IEntityPropertyAdaptor} implementation for xml property.
+ * {@link IEntityPropertyAdaptor} implementation for xml property with lazy evaluation of rendered
+ * value using XSLT script.
  * 
  * @author Piotr Buczek
  */
@@ -28,6 +29,8 @@ class XmlPropertyAdaptor extends BasicPropertyAdaptor
 {
     private final String xsltTransformation;
 
+    private String renderedValue = null;
+
     public XmlPropertyAdaptor(String code, String value, EntityPropertyPE propertyPE,
             String xsltTransformation)
     {
@@ -42,6 +45,15 @@ class XmlPropertyAdaptor extends BasicPropertyAdaptor
 
     @Override
     public String renderedValue()
+    {
+        if (renderedValue == null)
+        {
+            renderedValue = doRenderValue();
+        }
+        return renderedValue;
+    }
+
+    private String doRenderValue()
     {
         final String xml = super.valueAsString();
         return XmlUtils.transform(xsltTransformation, xml);