diff --git a/README.md b/README.md
index 9e25b9e..01809fc 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,148 @@
-# python-ooui
-Port of ooui.js to Python
+# Python OOUI
-## Testing
+Python OOUI (Open Object User Interface) is a Python port of ooui.js, providing powerful tools for data visualization and processing.
-```shell
+## Features
+
+- **Graph Processing**: Create line charts, bar charts, pie charts, and indicators
+- **Tree Views**: Handle structured data with advanced filtering and conditional formatting
+- **Data Helpers**: Utilities for domain parsing, condition evaluation, and data aggregation
+- **XML Parsing**: Parse XML-based graph and tree definitions
+- **Cross-Platform**: Compatible with Python 2.7+ and Python 3.x
+
+## Quick Start
+
+### Installation
+
+```bash
+pip install ooui
+```
+
+### Basic Usage
+
+```python
+from ooui.graph import parse_graph
+from ooui.tree import parse_tree
+
+# Create a line chart
+graph_xml = '''
+
+
+
+
+'''
+graph = parse_graph(graph_xml)
+
+# Create a tree view
+tree_xml = '''
+
+
+
+
+
+'''
+tree = parse_tree(tree_xml)
+```
+
+## Documentation
+
+📚 **[Complete Documentation](docs/index.md)** - Start here for comprehensive guides and examples
+
+### Quick Links
+
+- **[Installation Guide](docs/installation.md)** - Detailed setup instructions
+- **[Usage Guide](docs/usage.md)** - Core concepts and basic usage
+- **[API Reference](docs/api-reference.md)** - Complete API documentation
+- **[Examples](docs/examples.md)** - Practical code examples
+- **[Advanced Usage](docs/advanced-usage.md)** - Complex scenarios and advanced features
+
+## Key Components
+
+### Graph Processing
+```python
+from ooui.graph import parse_graph
+
+# Support for multiple chart types
+graph = parse_graph(xml_definition)
+result = graph.process(data, fields)
+```
+
+### Tree Views
+```python
+from ooui.tree import parse_tree
+
+# Structured data with conditional formatting
+tree = parse_tree(xml_definition)
+conditional_fields = tree.fields_in_conditions
+```
+
+### Condition Evaluation
+```python
+from ooui.helpers import ConditionParser
+
+parser = ConditionParser("red:amount < 100;green:amount >= 100")
+result = parser.eval({'amount': 150}) # Returns "green"
+```
+
+### Domain Parsing
+```python
+from ooui.helpers import Domain
+
+domain = Domain("[('active', '=', True), ('age', '>', 18)]")
+parsed = domain.parse({'user_id': 42})
+```
+
+## Development
+
+### Setting Up Development Environment
+
+```bash
+# Clone the repository
+git clone https://github.com/gisce/python-ooui.git
+cd python-ooui
+
+# Install in development mode
pip install -e .
+
+# Install development dependencies
pip install -r requirements-dev.txt
+```
+
+### Running Tests
+
+```bash
+# Run all tests
mamba
+
+# Tests use mamba (BDD testing framework)
+# See spec/ directory for test specifications
```
+
+### Project Structure
+
+```
+ooui/
+├── graph/ # Graph processing (charts, indicators)
+├── tree/ # Tree view processing
+└── helpers/ # Utilities (conditions, domain, dates, etc.)
+```
+
+## Contributing
+
+Contributions are welcome! Please:
+
+1. Check the [documentation](docs/) to understand the project
+2. Review existing [examples](docs/examples.md) and [API reference](docs/api-reference.md)
+3. Follow the existing code style and patterns
+4. Add tests for new functionality
+5. Update documentation as needed
+
+## License
+
+MIT License - see LICENSE file for details.
+
+## About
+
+Developed by [GISCE](https://gisce.net) for the GISCE-ERP project.
+
+For more information, visit the [complete documentation](docs/index.md).
diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md
new file mode 100644
index 0000000..977577f
--- /dev/null
+++ b/docs/advanced-usage.md
@@ -0,0 +1,873 @@
+# Advanced Usage
+
+This guide covers advanced features and complex usage scenarios of Python OOUI.
+
+## Advanced Graph Processing
+
+### Custom Graph Types and Extensions
+
+While Python OOUI comes with built-in graph types, you can understand and work with the underlying system:
+
+```python
+from ooui.graph import GRAPH_TYPES, parse_graph
+from ooui.graph.base import Graph
+
+# Check available graph types
+print("Available graph types:", list(GRAPH_TYPES.keys()))
+
+# Understand the graph type mapping
+for graph_type, graph_class in GRAPH_TYPES.items():
+ print(f"{graph_type} -> {graph_class.__name__}")
+```
+
+### Complex Multi-Axis Charts
+
+```python
+# Advanced chart with multiple Y-axes and grouping
+complex_chart_xml = '''
+
+
+
+
+
+
+
+'''
+
+chart = parse_graph(complex_chart_xml)
+
+# Advanced data with multiple dimensions
+complex_data = [
+ {
+ 'date': '2023-01-01', 'revenue': 10000, 'profit_margin': 0.15,
+ 'customer_count': 50, 'sales_rep': 'Alice', 'region': 'North'
+ },
+ {
+ 'date': '2023-01-01', 'revenue': 8000, 'profit_margin': 0.18,
+ 'customer_count': 35, 'sales_rep': 'Bob', 'region': 'South'
+ },
+ # ... more data
+]
+
+# Process with advanced options
+options = {
+ 'group_by_date': True,
+ 'aggregate_function': 'sum',
+ 'time_granularity': 'month'
+}
+
+result = chart.process(complex_data, {
+ 'date': {'type': 'date'},
+ 'revenue': {'type': 'float'},
+ 'profit_margin': {'type': 'float'},
+ 'customer_count': {'type': 'integer'},
+ 'sales_rep': {'type': 'char'}
+}, options)
+```
+
+### Dynamic Graph Configuration
+
+```python
+class DynamicGraphBuilder:
+ """Build graphs dynamically based on configuration."""
+
+ def __init__(self):
+ self.graph_templates = {
+ 'time_series': '''
+
+
+
+
+ ''',
+ 'comparison': '''
+
+
+
+
+ ''',
+ 'distribution': '''
+
+
+
+
+ '''
+ }
+
+ def build_graph(self, graph_type, config):
+ """Build a graph from configuration."""
+ if graph_type not in self.graph_templates:
+ raise ValueError(f"Unknown graph type: {graph_type}")
+
+ template = self.graph_templates[graph_type]
+ xml = template.format(**config)
+
+ return parse_graph(xml)
+
+ def build_dashboard(self, dashboard_config):
+ """Build multiple graphs for a dashboard."""
+ graphs = {}
+
+ for graph_name, graph_spec in dashboard_config.items():
+ graph_type = graph_spec.pop('type')
+ graphs[graph_name] = self.build_graph(graph_type, graph_spec)
+
+ return graphs
+
+# Usage
+builder = DynamicGraphBuilder()
+
+dashboard_config = {
+ 'sales_trend': {
+ 'type': 'time_series',
+ 'title': 'Sales Trend',
+ 'time_field': 'date',
+ 'value_field': 'amount',
+ 'operator': 'sum'
+ },
+ 'product_comparison': {
+ 'type': 'comparison',
+ 'title': 'Product Performance',
+ 'category_field': 'product',
+ 'value_field': 'revenue',
+ 'operator': 'sum'
+ },
+ 'regional_distribution': {
+ 'type': 'distribution',
+ 'title': 'Regional Sales Distribution',
+ 'category_field': 'region',
+ 'value_field': 'sales',
+ 'operator': 'sum'
+ }
+}
+
+dashboard_graphs = builder.build_dashboard(dashboard_config)
+```
+
+## Advanced Tree Processing
+
+### Dynamic Tree Configuration with Complex Conditions
+
+```python
+class AdvancedTreeProcessor:
+ """Advanced tree processing with dynamic conditions."""
+
+ def __init__(self):
+ self.condition_builders = {
+ 'status_colors': self._build_status_colors,
+ 'priority_colors': self._build_priority_colors,
+ 'threshold_colors': self._build_threshold_colors,
+ 'multi_condition': self._build_multi_condition
+ }
+
+ def _build_status_colors(self, config):
+ """Build status-based color conditions."""
+ status_map = config.get('status_map', {})
+ conditions = []
+
+ for status, color in status_map.items():
+ conditions.append(f"{color}:status=='{status}'")
+
+ return ';'.join(conditions)
+
+ def _build_priority_colors(self, config):
+ """Build priority-based color conditions."""
+ priority_colors = config.get('priority_colors', {})
+ conditions = []
+
+ for priority, color in priority_colors.items():
+ conditions.append(f"{color}:priority=='{priority}'")
+
+ return ';'.join(conditions)
+
+ def _build_threshold_colors(self, config):
+ """Build threshold-based color conditions."""
+ field = config.get('field')
+ thresholds = config.get('thresholds', [])
+
+ conditions = []
+ for threshold in thresholds:
+ operator = threshold.get('operator', '>=')
+ value = threshold['value']
+ color = threshold['color']
+ conditions.append(f"{color}:{field} {operator} {value}")
+
+ return ';'.join(conditions)
+
+ def _build_multi_condition(self, config):
+ """Build complex multi-field conditions."""
+ rules = config.get('rules', [])
+ conditions = []
+
+ for rule in rules:
+ result = rule['result']
+ condition_parts = []
+
+ for condition in rule['conditions']:
+ field = condition['field']
+ operator = condition['operator']
+ value = condition['value']
+
+ if isinstance(value, str):
+ condition_parts.append(f"{field} {operator} '{value}'")
+ else:
+ condition_parts.append(f"{field} {operator} {value}")
+
+ logical_op = rule.get('logical_operator', 'and')
+ full_condition = f" {logical_op} ".join(condition_parts)
+ conditions.append(f"{result}:{full_condition}")
+
+ return ';'.join(conditions)
+
+ def build_tree(self, fields, condition_config=None):
+ """Build a tree with dynamic conditions."""
+ field_elements = []
+ for field in fields:
+ if isinstance(field, str):
+ field_elements.append(f'')
+ else:
+ field_elements.append(f'')
+
+ fields_xml = '\n '.join(field_elements)
+
+ tree_attrs = ['string="Dynamic Tree"']
+
+ if condition_config:
+ for condition_type, config in condition_config.items():
+ if condition_type in self.condition_builders:
+ condition_string = self.condition_builders[condition_type](config)
+ tree_attrs.append(f'{condition_type}="{condition_string}"')
+
+ attrs_str = ' '.join(tree_attrs)
+
+ xml = f'''
+
+ {fields_xml}
+
+ '''
+
+ return parse_tree(xml)
+
+# Usage
+processor = AdvancedTreeProcessor()
+
+# Complex condition configuration
+condition_config = {
+ 'colors': {
+ 'rules': [
+ {
+ 'result': 'red',
+ 'conditions': [
+ {'field': 'status', 'operator': '==', 'value': 'overdue'},
+ {'field': 'amount', 'operator': '>', 'value': 1000}
+ ],
+ 'logical_operator': 'and'
+ },
+ {
+ 'result': 'orange',
+ 'conditions': [
+ {'field': 'priority', 'operator': '==', 'value': 'high'},
+ {'field': 'days_remaining', 'operator': '<=', 'value': 3}
+ ],
+ 'logical_operator': 'and'
+ }
+ ]
+ }
+}
+
+fields = [
+ 'name',
+ 'status',
+ 'priority',
+ 'amount',
+ 'days_remaining'
+]
+
+advanced_tree = processor.build_tree(fields, {'colors': condition_config['colors']})
+```
+
+## Advanced Condition Processing
+
+### Custom Condition Evaluators
+
+```python
+from ooui.helpers.conditions import ConditionParser
+import re
+from datetime import datetime, timedelta
+
+class AdvancedConditionParser(ConditionParser):
+ """Extended condition parser with custom functions."""
+
+ def __init__(self, condition):
+ super().__init__(condition)
+
+ # Add custom functions
+ self.functions.update({
+ 'days_ago': self._days_ago,
+ 'in_range': self._in_range,
+ 'matches': self._matches_regex,
+ 'calculate_age': self._calculate_age,
+ })
+
+ def _days_ago(self, days):
+ """Calculate date N days ago."""
+ return (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
+
+ def _in_range(self, value, min_val, max_val):
+ """Check if value is in range."""
+ return min_val <= value <= max_val
+
+ def _matches_regex(self, text, pattern):
+ """Check if text matches regex pattern."""
+ return bool(re.match(pattern, str(text)))
+
+ def _calculate_age(self, birth_date):
+ """Calculate age from birth date."""
+ if isinstance(birth_date, str):
+ birth = datetime.strptime(birth_date, '%Y-%m-%d')
+ else:
+ birth = birth_date
+
+ today = datetime.now()
+ return (today - birth).days // 365
+
+# Usage
+advanced_conditions = """
+urgent:days_remaining <= 1 and priority == 'high';
+warning:in_range(score, 60, 79) and department == 'sales';
+elderly:calculate_age(birth_date) >= 65;
+valid_email:matches(email, r'^[\\w\\.-]+@[\\w\\.-]+\\.\\w+$');
+recent:created_date >= days_ago(30)
+"""
+
+parser = AdvancedConditionParser(advanced_conditions)
+
+# Test data
+test_data = {
+ 'days_remaining': 0,
+ 'priority': 'high',
+ 'score': 75,
+ 'department': 'sales',
+ 'birth_date': '1950-01-01',
+ 'email': 'user@example.com',
+ 'created_date': '2023-10-01'
+}
+
+result = parser.eval(test_data)
+print(f"Condition result: {result}")
+```
+
+### Condition Caching and Performance
+
+```python
+from functools import lru_cache
+from ooui.helpers.conditions import ConditionParser
+
+class CachedConditionParser:
+ """Condition parser with caching for better performance."""
+
+ def __init__(self, max_cache_size=1000):
+ self.max_cache_size = max_cache_size
+ self._parsers = {}
+
+ @lru_cache(maxsize=1000)
+ def _get_parser(self, condition_string):
+ """Get cached parser for condition string."""
+ return ConditionParser(condition_string)
+
+ def eval_condition(self, condition_string, values):
+ """Evaluate condition with caching."""
+ parser = self._get_parser(condition_string)
+ return parser.eval(values)
+
+ def bulk_evaluate(self, condition_string, value_list):
+ """Evaluate condition against multiple value sets."""
+ parser = self._get_parser(condition_string)
+ results = []
+
+ for values in value_list:
+ result = parser.eval(values)
+ results.append(result)
+
+ return results
+
+ def clear_cache(self):
+ """Clear the condition parser cache."""
+ self._get_parser.cache_clear()
+
+# Usage for high-performance scenarios
+cached_parser = CachedConditionParser()
+
+# Evaluate same condition against many records
+condition = "red:amount < 1000;orange:amount < 5000;green:amount >= 5000"
+records = [
+ {'amount': 500},
+ {'amount': 2500},
+ {'amount': 7500},
+ # ... thousands more records
+]
+
+results = cached_parser.bulk_evaluate(condition, records)
+print(f"Processed {len(results)} records")
+```
+
+## Advanced Domain Processing
+
+### Complex Domain Builder
+
+```python
+from ooui.helpers.domain import Domain
+import json
+
+class DomainBuilder:
+ """Build complex domains programmatically."""
+
+ def __init__(self):
+ self.operators = {
+ 'eq': '=',
+ 'ne': '!=',
+ 'gt': '>',
+ 'gte': '>=',
+ 'lt': '<',
+ 'lte': '<=',
+ 'like': 'like',
+ 'ilike': 'ilike',
+ 'in': 'in',
+ 'not_in': 'not in'
+ }
+
+ def build_filter(self, field, operator, value):
+ """Build a single filter clause."""
+ op = self.operators.get(operator, operator)
+ return (field, op, value)
+
+ def build_and_domain(self, filters):
+ """Build AND domain from filter list."""
+ domain = []
+ for filter_spec in filters:
+ if isinstance(filter_spec, dict):
+ filter_clause = self.build_filter(
+ filter_spec['field'],
+ filter_spec['operator'],
+ filter_spec['value']
+ )
+ else:
+ filter_clause = filter_spec
+ domain.append(filter_clause)
+ return domain
+
+ def build_or_domain(self, filter_groups):
+ """Build OR domain from filter groups."""
+ domain = []
+
+ for i, group in enumerate(filter_groups):
+ if i > 0:
+ domain.append('|')
+
+ if isinstance(group, list):
+ domain.extend(self.build_and_domain(group))
+ else:
+ domain.append(group)
+
+ return domain
+
+ def build_complex_domain(self, domain_spec):
+ """Build complex nested domain."""
+ if domain_spec['type'] == 'and':
+ return self.build_and_domain(domain_spec['filters'])
+ elif domain_spec['type'] == 'or':
+ return self.build_or_domain(domain_spec['groups'])
+ else:
+ raise ValueError(f"Unknown domain type: {domain_spec['type']}")
+
+# Usage
+builder = DomainBuilder()
+
+# Complex search criteria
+search_criteria = {
+ 'type': 'and',
+ 'filters': [
+ {'field': 'active', 'operator': 'eq', 'value': True},
+ {'field': 'created_date', 'operator': 'gte', 'value': '2023-01-01'},
+ {
+ 'type': 'or',
+ 'groups': [
+ [
+ {'field': 'type', 'operator': 'eq', 'value': 'premium'},
+ {'field': 'amount', 'operator': 'gte', 'value': 1000}
+ ],
+ [
+ {'field': 'priority', 'operator': 'eq', 'value': 'high'}
+ ]
+ ]
+ }
+ ]
+}
+
+complex_domain = builder.build_complex_domain(search_criteria)
+domain_obj = Domain(str(complex_domain))
+parsed = domain_obj.parse()
+print("Complex domain:", json.dumps(parsed, indent=2))
+```
+
+### Dynamic Domain Evaluation
+
+```python
+class DynamicDomainEvaluator:
+ """Evaluate domains against data sets."""
+
+ def __init__(self):
+ self.type_converters = {
+ 'date': self._convert_date,
+ 'datetime': self._convert_datetime,
+ 'int': int,
+ 'float': float,
+ 'bool': bool,
+ 'str': str
+ }
+
+ def _convert_date(self, value):
+ """Convert string to date."""
+ if isinstance(value, str):
+ return datetime.strptime(value, '%Y-%m-%d').date()
+ return value
+
+ def _convert_datetime(self, value):
+ """Convert string to datetime."""
+ if isinstance(value, str):
+ return datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
+ return value
+
+ def evaluate_record(self, record, domain_filters, field_types=None):
+ """Check if record matches domain filters."""
+ if field_types is None:
+ field_types = {}
+
+ for domain_filter in domain_filters:
+ if isinstance(domain_filter, str):
+ continue # Skip logical operators
+
+ field, operator, expected = domain_filter
+
+ if field not in record:
+ return False
+
+ actual = record[field]
+
+ # Type conversion if needed
+ if field in field_types:
+ field_type = field_types[field]
+ if field_type in self.type_converters:
+ converter = self.type_converters[field_type]
+ try:
+ actual = converter(actual)
+ if not isinstance(expected, type(actual)):
+ expected = converter(expected)
+ except (ValueError, TypeError):
+ return False
+
+ # Evaluate condition
+ if not self._evaluate_condition(actual, operator, expected):
+ return False
+
+ return True
+
+ def _evaluate_condition(self, actual, operator, expected):
+ """Evaluate single condition."""
+ try:
+ if operator == '=':
+ return actual == expected
+ elif operator == '!=':
+ return actual != expected
+ elif operator == '>':
+ return actual > expected
+ elif operator == '>=':
+ return actual >= expected
+ elif operator == '<':
+ return actual < expected
+ elif operator == '<=':
+ return actual <= expected
+ elif operator == 'like':
+ return str(expected).lower() in str(actual).lower()
+ elif operator == 'ilike':
+ return str(expected).lower() in str(actual).lower()
+ elif operator == 'in':
+ return actual in expected
+ elif operator == 'not in':
+ return actual not in expected
+ else:
+ return False
+ except (TypeError, ValueError):
+ return False
+
+ def filter_dataset(self, dataset, domain_string, field_types=None):
+ """Filter entire dataset using domain."""
+ domain = Domain(domain_string)
+ domain_filters = domain.parse()
+
+ filtered = []
+ for record in dataset:
+ if self.evaluate_record(record, domain_filters, field_types):
+ filtered.append(record)
+
+ return filtered
+
+# Usage
+evaluator = DynamicDomainEvaluator()
+
+# Sample dataset
+dataset = [
+ {'id': 1, 'name': 'Alice', 'age': 30, 'active': True, 'created': '2023-01-15'},
+ {'id': 2, 'name': 'Bob', 'age': 25, 'active': False, 'created': '2023-02-20'},
+ {'id': 3, 'name': 'Charlie', 'age': 35, 'active': True, 'created': '2023-03-10'},
+]
+
+# Complex filter
+domain_string = "[('active', '=', True), ('age', '>', 28), ('created', '>=', '2023-02-01')]"
+field_types = {
+ 'age': 'int',
+ 'active': 'bool',
+ 'created': 'date'
+}
+
+filtered_data = evaluator.filter_dataset(dataset, domain_string, field_types)
+print("Filtered data:", filtered_data)
+```
+
+## Performance Optimization
+
+### Batch Processing
+
+```python
+class BatchProcessor:
+ """Process large datasets in batches."""
+
+ def __init__(self, batch_size=1000):
+ self.batch_size = batch_size
+
+ def process_graphs_in_batches(self, graph, dataset, fields):
+ """Process graph data in batches for memory efficiency."""
+ results = []
+
+ for i in range(0, len(dataset), self.batch_size):
+ batch = dataset[i:i + self.batch_size]
+ batch_result = graph.process(batch, fields)
+ results.append(batch_result)
+
+ # Combine results
+ return self._combine_graph_results(results)
+
+ def _combine_graph_results(self, results):
+ """Combine batch results into single result."""
+ if not results:
+ return None
+
+ # Implementation depends on graph type and result structure
+ combined = results[0]
+
+ for result in results[1:]:
+ # Merge logic here - depends on specific result format
+ pass
+
+ return combined
+
+ def process_conditions_in_batches(self, condition_parser, dataset):
+ """Evaluate conditions in batches."""
+ results = []
+
+ for i in range(0, len(dataset), self.batch_size):
+ batch = dataset[i:i + self.batch_size]
+ batch_results = []
+
+ for record in batch:
+ result = condition_parser.eval(record)
+ batch_results.append(result)
+
+ results.extend(batch_results)
+
+ return results
+
+# Memory-efficient processing
+processor = BatchProcessor(batch_size=500)
+
+# Large dataset processing
+large_dataset = [{'value': i, 'category': f'cat_{i%10}'} for i in range(10000)]
+
+# Process in batches to manage memory
+batch_results = processor.process_conditions_in_batches(
+ ConditionParser("high:value > 5000;low:value <= 5000"),
+ large_dataset
+)
+```
+
+### Caching Strategies
+
+```python
+import pickle
+import hashlib
+from functools import wraps
+
+class ResultCache:
+ """Cache processing results for better performance."""
+
+ def __init__(self, cache_dir=None):
+ self.cache_dir = cache_dir or '/tmp/ooui_cache'
+ self.memory_cache = {}
+ self.max_memory_items = 100
+
+ def _generate_key(self, *args, **kwargs):
+ """Generate cache key from arguments."""
+ content = str(args) + str(sorted(kwargs.items()))
+ return hashlib.md5(content.encode()).hexdigest()
+
+ def cache_result(self, key, result):
+ """Cache result in memory."""
+ if len(self.memory_cache) >= self.max_memory_items:
+ # Remove oldest item
+ oldest_key = next(iter(self.memory_cache))
+ del self.memory_cache[oldest_key]
+
+ self.memory_cache[key] = result
+
+ def get_cached_result(self, key):
+ """Get cached result."""
+ return self.memory_cache.get(key)
+
+ def cached_process(self, func):
+ """Decorator for caching function results."""
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ key = self._generate_key(*args, **kwargs)
+
+ # Check memory cache
+ result = self.get_cached_result(key)
+ if result is not None:
+ return result
+
+ # Execute function and cache result
+ result = func(*args, **kwargs)
+ self.cache_result(key, result)
+
+ return result
+
+ return wrapper
+
+# Usage
+cache = ResultCache()
+
+@cache.cached_process
+def expensive_graph_processing(graph, data, fields):
+ """Expensive processing that benefits from caching."""
+ return graph.process(data, fields)
+
+# Subsequent calls with same parameters will use cache
+result1 = expensive_graph_processing(my_graph, my_data, my_fields)
+result2 = expensive_graph_processing(my_graph, my_data, my_fields) # From cache
+```
+
+## Integration Patterns
+
+### Plugin Architecture
+
+```python
+class OOUIPlugin:
+ """Base class for OOUI plugins."""
+
+ def __init__(self, name):
+ self.name = name
+
+ def process_graph_data(self, graph, data, fields):
+ """Override to add custom graph processing."""
+ return graph.process(data, fields)
+
+ def process_tree_data(self, tree, data):
+ """Override to add custom tree processing."""
+ return data
+
+ def enhance_conditions(self, condition_string):
+ """Override to add custom condition enhancements."""
+ return condition_string
+
+class ExportPlugin(OOUIPlugin):
+ """Plugin for data export functionality."""
+
+ def __init__(self):
+ super().__init__('export')
+ self.formats = ['csv', 'json', 'xlsx']
+
+ def export_graph_data(self, graph_data, format='json'):
+ """Export graph data to various formats."""
+ if format == 'json':
+ return json.dumps(graph_data, indent=2)
+ elif format == 'csv':
+ return self._to_csv(graph_data)
+ else:
+ raise ValueError(f"Unsupported format: {format}")
+
+ def _to_csv(self, data):
+ """Convert data to CSV format."""
+ # Implementation depends on data structure
+ return "CSV data here"
+
+class ValidationPlugin(OOUIPlugin):
+ """Plugin for data validation."""
+
+ def __init__(self):
+ super().__init__('validation')
+ self.rules = {}
+
+ def add_validation_rule(self, field, rule):
+ """Add validation rule for field."""
+ self.rules[field] = rule
+
+ def validate_data(self, data):
+ """Validate data against rules."""
+ errors = []
+
+ for record in data:
+ for field, rule in self.rules.items():
+ if field in record:
+ if not rule(record[field]):
+ errors.append(f"Validation failed for {field}: {record[field]}")
+
+ return errors
+
+class PluginManager:
+ """Manager for OOUI plugins."""
+
+ def __init__(self):
+ self.plugins = {}
+
+ def register_plugin(self, plugin):
+ """Register a plugin."""
+ self.plugins[plugin.name] = plugin
+
+ def get_plugin(self, name):
+ """Get plugin by name."""
+ return self.plugins.get(name)
+
+ def process_with_plugins(self, operation, *args, **kwargs):
+ """Process operation through relevant plugins."""
+ results = {}
+
+ for name, plugin in self.plugins.items():
+ if hasattr(plugin, operation):
+ method = getattr(plugin, operation)
+ results[name] = method(*args, **kwargs)
+
+ return results
+
+# Usage
+manager = PluginManager()
+manager.register_plugin(ExportPlugin())
+manager.register_plugin(ValidationPlugin())
+
+# Use plugins
+export_plugin = manager.get_plugin('export')
+validation_plugin = manager.get_plugin('validation')
+
+# Add validation rules
+validation_plugin.add_validation_rule('age', lambda x: 0 <= x <= 150)
+validation_plugin.add_validation_rule('email', lambda x: '@' in x)
+```
+
+This advanced usage guide demonstrates sophisticated patterns and techniques for working with Python OOUI in complex scenarios, including performance optimization, extensibility, and integration patterns.
\ No newline at end of file
diff --git a/docs/api-reference.md b/docs/api-reference.md
new file mode 100644
index 0000000..ea29cd6
--- /dev/null
+++ b/docs/api-reference.md
@@ -0,0 +1,473 @@
+# API Reference
+
+Complete API documentation for Python OOUI.
+
+## Module Structure
+
+```
+ooui/
+├── graph/ # Graph processing components
+│ ├── __init__.py # parse_graph()
+│ ├── base.py # Graph base class
+│ ├── chart.py # GraphChart class
+│ ├── indicator.py # GraphIndicator classes
+│ ├── axis.py # Axis processing
+│ ├── fields.py # Field operations
+│ ├── processor.py # Data processing utilities
+│ └── timerange.py # Time range handling
+├── tree/ # Tree view components
+│ ├── __init__.py # parse_tree()
+│ └── base.py # Tree class
+└── helpers/ # Utility modules
+ ├── __init__.py # Common utilities
+ ├── conditions.py # ConditionParser
+ ├── domain.py # Domain class
+ ├── aggregated.py # Aggregator class
+ ├── dates.py # Date utilities
+ └── features.py # Feature detection
+```
+
+## Graph Module (`ooui.graph`)
+
+### parse_graph(xml)
+
+Parse a graph definition from XML string.
+
+**Parameters:**
+- `xml` (str): XML string containing graph definition
+
+**Returns:**
+- Graph object (GraphChart, GraphIndicator, or GraphIndicatorField)
+
+**Raises:**
+- `ValueError`: If graph type is invalid or unsupported
+
+**Example:**
+```python
+from ooui.graph import parse_graph
+
+xml = '''
+
+
+
+
+'''
+graph = parse_graph(xml)
+```
+
+### Graph Base Class
+
+Base class for all graph types.
+
+#### Properties
+
+- `string`: Graph title/label
+- `type`: Graph type (line, bar, pie, indicator, indicatorField)
+- `fields`: List of field names used in the graph
+
+#### Methods
+
+##### process(values, fields, options=None)
+
+Process data for the graph.
+
+**Parameters:**
+- `values` (list): List of data dictionaries
+- `fields` (dict): Field definitions
+- `options` (dict, optional): Processing options
+
+**Returns:**
+- Processed data structure ready for visualization
+
+### GraphChart Class
+
+Chart-type graphs (line, bar, pie).
+
+#### Properties
+
+- `x`: X-axis configuration
+- `y`: Y-axis configuration (list of axis objects)
+
+#### Methods
+
+Same as Graph base class plus chart-specific processing.
+
+**Example:**
+```python
+# Sample data processing
+data = [
+ {'date': '2023-01-01', 'sales': 1000},
+ {'date': '2023-01-02', 'sales': 1200}
+]
+fields = {
+ 'date': {'type': 'date'},
+ 'sales': {'type': 'float'}
+}
+result = chart.process(data, fields)
+```
+
+### GraphIndicator Class
+
+Single-value indicator graphs.
+
+#### Properties
+
+- `field`: Main field configuration
+- `compare_field`: Optional comparison field
+
+#### Methods
+
+##### get_indicator_value(values, fields)
+
+Calculate the indicator value.
+
+**Example:**
+```python
+xml = '''
+
+
+
+'''
+indicator = parse_graph(xml)
+```
+
+### GraphIndicatorField Class
+
+Field-based indicators with multiple values.
+
+Similar to GraphIndicator but handles multiple field indicators.
+
+## Tree Module (`ooui.tree`)
+
+### parse_tree(xml)
+
+Parse a tree view definition from XML.
+
+**Parameters:**
+- `xml` (str): XML string containing tree definition
+
+**Returns:**
+- Tree object
+
+**Example:**
+```python
+from ooui.tree import parse_tree
+
+xml = '''
+
+
+
+
+'''
+tree = parse_tree(xml)
+```
+
+### Tree Class
+
+Represents a tree view configuration.
+
+#### Properties
+
+- `string`: Tree title/label
+- `infinite`: Whether tree supports infinite scrolling
+- `colors`: Color condition string
+- `status`: Status condition string
+- `editable`: Edit mode (top, bottom, etc.)
+- `fields`: List of field elements
+- `fields_in_conditions`: Dict of fields used in color/status conditions
+
+#### Methods
+
+Tree objects are primarily data containers. Field processing is handled by the parsing system.
+
+**Example:**
+```python
+# Access tree properties
+print(tree.string) # "Customer List"
+print(tree.editable) # "top"
+print(len(tree.fields)) # 2
+
+# Check conditional fields
+if tree.colors:
+ conditional = tree.fields_in_conditions
+ print(conditional.get('colors', [])) # Fields used in color conditions
+```
+
+## Helpers Module (`ooui.helpers`)
+
+### Utility Functions
+
+#### parse_bool_attribute(attribute)
+
+Parse boolean values from string representations.
+
+**Parameters:**
+- `attribute`: Value to parse (string, int, or bool)
+
+**Returns:**
+- `True` for "1", "true" (case-insensitive)
+- `False` otherwise
+
+**Example:**
+```python
+from ooui.helpers import parse_bool_attribute
+
+print(parse_bool_attribute('1')) # True
+print(parse_bool_attribute('True')) # True
+print(parse_bool_attribute('0')) # False
+```
+
+#### replace_entities(text)
+
+Replace HTML entities with Unicode characters.
+
+**Parameters:**
+- `text` (str): Text containing HTML entities
+
+**Returns:**
+- Cleaned text string
+
+**Example:**
+```python
+from ooui.helpers import replace_entities
+
+text = "Price > $100 & < $200"
+clean = replace_entities(text)
+print(clean) # "Price > $100 & < $200"
+```
+
+### ConditionParser Class (`ooui.helpers.conditions`)
+
+Parse and evaluate conditional expressions.
+
+#### Constructor
+
+```python
+ConditionParser(condition)
+```
+
+**Parameters:**
+- `condition` (str): Condition string in format "result1:condition1;result2:condition2"
+
+#### Properties
+
+- `involved_fields`: Set of field names used in conditions
+- `raw_condition`: Original condition string
+
+#### Methods
+
+##### eval(values)
+
+Evaluate conditions against provided values.
+
+**Parameters:**
+- `values` (dict): Field values to evaluate against
+
+**Returns:**
+- Result value if condition matches, None otherwise
+
+**Example:**
+```python
+from ooui.helpers import ConditionParser
+
+parser = ConditionParser("red:amount < 100;green:amount >= 100")
+print(parser.involved_fields) # {'amount'}
+
+result = parser.eval({'amount': 50})
+print(result) # "red"
+
+result = parser.eval({'amount': 150})
+print(result) # "green"
+```
+
+### Domain Class (`ooui.helpers.domain`)
+
+Parse and evaluate domain expressions (query filters).
+
+#### Constructor
+
+```python
+Domain(domain)
+```
+
+**Parameters:**
+- `domain` (str): Domain expression string
+
+#### Methods
+
+##### parse(values=None)
+
+Parse domain with optional variable substitution.
+
+**Parameters:**
+- `values` (dict, optional): Variable values for substitution
+
+**Returns:**
+- Parsed domain structure
+
+**Example:**
+```python
+from ooui.helpers import Domain
+
+# Simple domain
+domain = Domain("[('active', '=', True)]")
+result = domain.parse()
+
+# Domain with variables
+domain = Domain("[('user_id', '=', user)]")
+result = domain.parse({'user': 42})
+```
+
+### Aggregator Class (`ooui.helpers.aggregated`)
+
+Aggregate data with various operations.
+
+#### Constructor
+
+```python
+Aggregator(rules)
+```
+
+**Parameters:**
+- `rules` (dict): Aggregation rules mapping
+
+#### Methods
+
+##### aggregate(data, group_by=None)
+
+Aggregate data according to rules.
+
+**Parameters:**
+- `data` (list): List of data dictionaries
+- `group_by` (str, optional): Field name to group by
+
+**Returns:**
+- Aggregated data structure
+
+**Example:**
+```python
+from ooui.helpers.aggregated import Aggregator
+
+aggregator = Aggregator({
+ 'total': {'operator': 'sum', 'field': 'amount'},
+ 'count': {'operator': 'count', 'field': 'id'}
+})
+
+data = [
+ {'amount': 100, 'id': 1, 'category': 'A'},
+ {'amount': 200, 'id': 2, 'category': 'A'},
+ {'amount': 150, 'id': 3, 'category': 'B'}
+]
+
+result = aggregator.aggregate(data, group_by='category')
+# Result: {'A': {'total': 300, 'count': 2}, 'B': {'total': 150, 'count': 1}}
+```
+
+## Field Processing (`ooui.graph.fields`)
+
+### get_value_for_operator(values, operator)
+
+Apply aggregation operator to list of values.
+
+**Parameters:**
+- `values` (list): Numeric values
+- `operator` (str): Operation ('sum', 'avg', 'max', 'min', 'count')
+
+**Returns:**
+- Aggregated result
+
+**Example:**
+```python
+from ooui.graph.fields import get_value_for_operator
+
+values = [10, 20, 30, 40, 50]
+print(get_value_for_operator(values, 'sum')) # 150
+print(get_value_for_operator(values, 'avg')) # 30
+print(get_value_for_operator(values, 'max')) # 50
+print(get_value_for_operator(values, 'count')) # 5
+```
+
+## Date Processing (`ooui.helpers.dates`)
+
+### DateRange Class
+
+Represents a date range with start and end dates.
+
+#### Constructor
+
+```python
+DateRange(start, end)
+```
+
+**Parameters:**
+- `start`: Start date (string or datetime)
+- `end`: End date (string or datetime)
+
+#### Properties
+
+- `start`: Start datetime object
+- `end`: End datetime object
+
+### get_date_range(period)
+
+Get predefined date ranges.
+
+**Parameters:**
+- `period` (str): Period identifier ('today', 'this_week', 'this_month', etc.)
+
+**Returns:**
+- DateRange object
+
+**Example:**
+```python
+from ooui.helpers.dates import get_date_range, DateRange
+
+# Predefined ranges
+this_month = get_date_range('this_month')
+print(this_month.start)
+print(this_month.end)
+
+# Custom range
+custom = DateRange('2023-01-01', '2023-12-31')
+```
+
+## Error Handling
+
+### Common Exceptions
+
+- `ValueError`: Invalid graph types, malformed conditions
+- `AttributeError`: Missing required attributes
+- `KeyError`: Missing field references
+- `XMLSyntaxError`: Malformed XML (from lxml)
+
+### Error Handling Example
+
+```python
+try:
+ graph = parse_graph(xml_string)
+ result = graph.process(data, fields)
+except ValueError as e:
+ print(f"Configuration error: {e}")
+except Exception as e:
+ print(f"Processing error: {e}")
+```
+
+## Type Annotations
+
+Python OOUI supports both Python 2 and 3, so type annotations are not used in the source code. However, for modern development, expected types are:
+
+```python
+# Function signatures (for reference)
+def parse_graph(xml: str) -> Graph
+def parse_tree(xml: str) -> Tree
+def parse_bool_attribute(attribute: Union[str, int, bool]) -> bool
+def replace_entities(text: str) -> str
+
+class ConditionParser:
+ def __init__(self, condition: str) -> None
+ def eval(self, values: Dict[str, Any]) -> Optional[str]
+
+class Domain:
+ def __init__(self, domain: str) -> None
+ def parse(self, values: Optional[Dict[str, Any]] = None) -> Any
+```
\ No newline at end of file
diff --git a/docs/examples.md b/docs/examples.md
new file mode 100644
index 0000000..f309347
--- /dev/null
+++ b/docs/examples.md
@@ -0,0 +1,580 @@
+# Examples
+
+This page provides practical examples of using Python OOUI for various scenarios.
+
+## Graph Examples
+
+### Line Chart for Time Series Data
+
+```python
+from ooui.graph import parse_graph
+
+# Define a line chart for sales over time
+sales_chart_xml = '''
+
+
+
+
+'''
+
+# Parse the graph
+sales_graph = parse_graph(sales_chart_xml)
+
+# Sample data
+sales_data = [
+ {'month': '2023-01-01', 'revenue': 15000.0, 'sales_rep': 'John'},
+ {'month': '2023-01-01', 'revenue': 12000.0, 'sales_rep': 'Jane'},
+ {'month': '2023-02-01', 'revenue': 18000.0, 'sales_rep': 'John'},
+ {'month': '2023-02-01', 'revenue': 16000.0, 'sales_rep': 'Jane'},
+ {'month': '2023-03-01', 'revenue': 21000.0, 'sales_rep': 'John'},
+]
+
+# Field definitions
+fields = {
+ 'month': {'type': 'date', 'string': 'Month'},
+ 'revenue': {'type': 'float', 'string': 'Revenue'},
+ 'sales_rep': {'type': 'char', 'string': 'Sales Rep'}
+}
+
+# Process the data
+chart_data = sales_graph.process(sales_data, fields)
+print("Processed chart data:", chart_data)
+```
+
+### Bar Chart with Multiple Series
+
+```python
+# Bar chart comparing performance across categories
+performance_xml = '''
+
+
+
+
+
+'''
+
+performance_graph = parse_graph(performance_xml)
+
+performance_data = [
+ {'department': 'Sales', 'target': 100000, 'actual': 95000},
+ {'department': 'Marketing', 'target': 50000, 'actual': 52000},
+ {'department': 'Support', 'target': 30000, 'actual': 28000},
+]
+
+fields = {
+ 'department': {'type': 'char'},
+ 'target': {'type': 'float'},
+ 'actual': {'type': 'float'}
+}
+
+result = performance_graph.process(performance_data, fields)
+```
+
+### Pie Chart for Distribution Analysis
+
+```python
+# Pie chart showing market share
+market_share_xml = '''
+
+
+
+
+'''
+
+market_graph = parse_graph(market_share_xml)
+
+market_data = [
+ {'region': 'North America', 'sales': 450000},
+ {'region': 'Europe', 'sales': 380000},
+ {'region': 'Asia Pacific', 'sales': 290000},
+ {'region': 'Latin America', 'sales': 125000},
+ {'region': 'Africa', 'sales': 75000},
+]
+
+fields = {
+ 'region': {'type': 'char'},
+ 'sales': {'type': 'float'}
+}
+
+pie_data = market_graph.process(market_data, fields)
+```
+
+### Indicator for KPI Dashboard
+
+```python
+# Single KPI indicator
+kpi_xml = '''
+
+
+
+'''
+
+kpi_graph = parse_graph(kpi_xml)
+
+revenue_data = [
+ {'revenue': 15000},
+ {'revenue': 22000},
+ {'revenue': 18500},
+ {'revenue': 31000},
+]
+
+kpi_result = kpi_graph.process(revenue_data, {'revenue': {'type': 'float'}})
+print(f"Total Revenue: {kpi_result}")
+```
+
+## Tree View Examples
+
+### Basic Employee List
+
+```python
+from ooui.tree import parse_tree
+
+# Simple employee tree view
+employee_tree_xml = '''
+
+
+
+
+
+
+'''
+
+employee_tree = parse_tree(employee_tree_xml)
+
+print(f"Tree title: {employee_tree.string}")
+print(f"Editable: {employee_tree.editable}")
+print(f"Number of fields: {len(employee_tree.fields)}")
+```
+
+### Tree with Conditional Colors
+
+```python
+# Order list with status-based coloring
+order_tree_xml = '''
+
+
+
+
+
+
+
+'''
+
+order_tree = parse_tree(order_tree_xml)
+
+# Check which fields are used in conditions
+conditional_fields = order_tree.fields_in_conditions
+print(f"Fields in color conditions: {conditional_fields['colors']}")
+# Output: ['status']
+```
+
+### Tree with Status Indicators
+
+```python
+# Project list with status indicators
+project_tree_xml = '''
+
+
+
+
+
+
+
+'''
+
+project_tree = parse_tree(project_tree_xml)
+
+# Get all conditional fields
+all_conditions = project_tree.fields_in_conditions
+print("Color fields:", all_conditions.get('colors', []))
+print("Status fields:", all_conditions.get('status', []))
+```
+
+## Condition Parser Examples
+
+### Simple Status Conditions
+
+```python
+from ooui.helpers import ConditionParser
+
+# Define status-based conditions
+status_condition = "red:status=='error';yellow:status=='warning';green:status=='ok'"
+parser = ConditionParser(status_condition)
+
+# Test with different statuses
+test_cases = [
+ {'status': 'error'},
+ {'status': 'warning'},
+ {'status': 'ok'},
+ {'status': 'unknown'}
+]
+
+for case in test_cases:
+ result = parser.eval(case)
+ print(f"Status {case['status']} -> Color {result}")
+
+# Output:
+# Status error -> Color red
+# Status warning -> Color yellow
+# Status ok -> Color green
+# Status unknown -> Color None
+```
+
+### Numeric Range Conditions
+
+```python
+# Score-based color coding
+score_condition = "red:score < 60;yellow:score < 80;green:score >= 80"
+score_parser = ConditionParser(score_condition)
+
+scores = [45, 65, 72, 85, 92]
+for score in scores:
+ color = score_parser.eval({'score': score})
+ print(f"Score {score} -> {color}")
+```
+
+### Complex Multi-Field Conditions
+
+```python
+# Complex business logic
+complex_condition = """
+urgent:priority=='high' and days_remaining <= 1;
+warning:priority=='medium' and days_remaining <= 3;
+normal:priority=='low' or days_remaining > 7
+"""
+
+complex_parser = ConditionParser(complex_condition)
+
+test_scenarios = [
+ {'priority': 'high', 'days_remaining': 0},
+ {'priority': 'medium', 'days_remaining': 2},
+ {'priority': 'low', 'days_remaining': 5},
+ {'priority': 'medium', 'days_remaining': 10},
+]
+
+for scenario in test_scenarios:
+ result = complex_parser.eval(scenario)
+ print(f"{scenario} -> {result}")
+```
+
+## Domain Parser Examples
+
+### Basic Query Filters
+
+```python
+from ooui.helpers import Domain
+
+# Simple equality filter
+basic_domain = Domain("[('active', '=', True), ('type', '=', 'customer')]")
+result = basic_domain.parse()
+print("Basic domain:", result)
+
+# Range filter
+range_domain = Domain("[('age', '>=', 18), ('age', '<=', 65)]")
+result = range_domain.parse()
+print("Range domain:", result)
+```
+
+### Dynamic Domains with Variables
+
+```python
+# Domain with user-provided values
+user_domain = Domain("[('created_by', '=', user_id), ('date', '>=', start_date)]")
+
+# Provide values at runtime
+context = {
+ 'user_id': 42,
+ 'start_date': '2023-01-01'
+}
+
+parsed_domain = user_domain.parse(context)
+print("User domain:", parsed_domain)
+```
+
+### Complex Logical Operations
+
+```python
+# OR conditions
+or_domain = Domain("""
+[
+ '|',
+ ('state', '=', 'active'),
+ ('state', '=', 'pending'),
+ ('priority', '=', 'high')
+]
+""")
+
+result = or_domain.parse()
+print("OR domain:", result)
+```
+
+## Data Aggregation Examples
+
+### Sales Reporting
+
+```python
+from ooui.helpers.aggregated import Aggregator
+
+# Sales aggregation rules
+sales_aggregator = Aggregator({
+ 'total_sales': {'operator': 'sum', 'field': 'amount'},
+ 'avg_deal_size': {'operator': 'avg', 'field': 'amount'},
+ 'deal_count': {'operator': 'count', 'field': 'deal_id'},
+ 'largest_deal': {'operator': 'max', 'field': 'amount'},
+ 'smallest_deal': {'operator': 'min', 'field': 'amount'}
+})
+
+# Sample sales data
+sales_data = [
+ {'amount': 5000, 'deal_id': 1, 'rep': 'Alice', 'region': 'North'},
+ {'amount': 7500, 'deal_id': 2, 'rep': 'Bob', 'region': 'North'},
+ {'amount': 3200, 'deal_id': 3, 'rep': 'Charlie', 'region': 'South'},
+ {'amount': 9800, 'deal_id': 4, 'rep': 'Diana', 'region': 'South'},
+]
+
+# Aggregate by region
+regional_sales = sales_aggregator.aggregate(sales_data, group_by='region')
+print("Regional Sales:", regional_sales)
+
+# Aggregate by sales rep
+rep_sales = sales_aggregator.aggregate(sales_data, group_by='rep')
+print("Rep Sales:", rep_sales)
+
+# Overall aggregation (no grouping)
+total_sales = sales_aggregator.aggregate(sales_data)
+print("Total Sales:", total_sales)
+```
+
+### Performance Metrics
+
+```python
+# Website performance metrics
+perf_aggregator = Aggregator({
+ 'total_visits': {'operator': 'sum', 'field': 'visits'},
+ 'avg_load_time': {'operator': 'avg', 'field': 'load_time'},
+ 'bounce_rate': {'operator': 'avg', 'field': 'bounce_rate'},
+ 'peak_concurrent': {'operator': 'max', 'field': 'concurrent_users'}
+})
+
+performance_data = [
+ {'visits': 1200, 'load_time': 2.3, 'bounce_rate': 0.35, 'concurrent_users': 45, 'page': 'home'},
+ {'visits': 800, 'load_time': 1.8, 'bounce_rate': 0.28, 'concurrent_users': 32, 'page': 'products'},
+ {'visits': 600, 'load_time': 3.1, 'bounce_rate': 0.42, 'concurrent_users': 28, 'page': 'contact'},
+]
+
+page_metrics = perf_aggregator.aggregate(performance_data, group_by='page')
+print("Page Performance:", page_metrics)
+```
+
+## Date Range Examples
+
+### Time-based Analysis
+
+```python
+from ooui.helpers.dates import get_date_range, DateRange
+from datetime import datetime
+
+# Predefined ranges
+today = get_date_range('today')
+this_week = get_date_range('this_week')
+this_month = get_date_range('this_month')
+
+print(f"Today: {today.start} to {today.end}")
+print(f"This week: {this_week.start} to {this_week.end}")
+print(f"This month: {this_month.start} to {this_month.end}")
+
+# Custom date range
+quarter_start = DateRange('2023-01-01', '2023-03-31')
+print(f"Q1 2023: {quarter_start.start} to {quarter_start.end}")
+```
+
+### Filtering Data by Date Range
+
+```python
+# Filter sales data by date range
+def filter_by_date_range(data, date_field, date_range):
+ """Filter data within a date range."""
+ filtered = []
+ for record in data:
+ record_date = datetime.strptime(record[date_field], '%Y-%m-%d')
+ if date_range.start <= record_date <= date_range.end:
+ filtered.append(record)
+ return filtered
+
+# Sample sales data
+sales_records = [
+ {'date': '2023-01-15', 'amount': 1500},
+ {'date': '2023-02-20', 'amount': 2200},
+ {'date': '2023-03-10', 'amount': 1800},
+ {'date': '2023-04-05', 'amount': 2500},
+]
+
+# Filter for Q1
+q1_range = DateRange('2023-01-01', '2023-03-31')
+q1_sales = filter_by_date_range(sales_records, 'date', q1_range)
+print("Q1 Sales:", q1_sales)
+```
+
+## Field Operations Examples
+
+### Data Transformation
+
+```python
+from ooui.graph.fields import get_value_for_operator
+
+# Sample monthly sales figures
+monthly_sales = [12000, 15000, 11000, 18000, 22000, 19000]
+
+# Calculate various metrics
+total = get_value_for_operator(monthly_sales, 'sum')
+average = get_value_for_operator(monthly_sales, 'avg')
+best_month = get_value_for_operator(monthly_sales, 'max')
+worst_month = get_value_for_operator(monthly_sales, 'min')
+months_count = get_value_for_operator(monthly_sales, 'count')
+
+print(f"Total Sales: ${total:,.2f}")
+print(f"Average Monthly: ${average:,.2f}")
+print(f"Best Month: ${best_month:,.2f}")
+print(f"Worst Month: ${worst_month:,.2f}")
+print(f"Months Tracked: {months_count}")
+```
+
+## Utility Functions Examples
+
+### Boolean Parsing
+
+```python
+from ooui.helpers import parse_bool_attribute
+
+# Parse various boolean representations
+config_values = ['1', '0', 'true', 'false', 'True', 'False', 'yes', 'no']
+
+for value in config_values:
+ parsed = parse_bool_attribute(value)
+ print(f"'{value}' -> {parsed}")
+```
+
+### HTML Entity Cleanup
+
+```python
+from ooui.helpers import replace_entities
+
+# Clean HTML entities from text
+html_texts = [
+ "Price > $100",
+ "Q&A Section",
+ "<tag> content </tag>",
+ "R&D Department",
+ "50% < target < 75%"
+]
+
+for text in html_texts:
+ clean = replace_entities(text)
+ print(f"Original: {text}")
+ print(f"Cleaned: {clean}\n")
+```
+
+## Complete Integration Example
+
+### Dashboard Data Processing
+
+```python
+from ooui.graph import parse_graph
+from ooui.tree import parse_tree
+from ooui.helpers import ConditionParser, Aggregator
+from ooui.helpers.dates import get_date_range
+
+# Complete dashboard setup
+class SalesDashboard:
+ def __init__(self):
+ # Define graphs
+ self.sales_trend = parse_graph('''
+
+
+
+
+ ''')
+
+ self.top_products = parse_graph('''
+
+
+
+
+ ''')
+
+ # Define tree view
+ self.sales_list = parse_tree('''
+
+
+
+
+
+
+ ''')
+
+ # Setup aggregation
+ self.aggregator = Aggregator({
+ 'total_revenue': {'operator': 'sum', 'field': 'amount'},
+ 'avg_deal_size': {'operator': 'avg', 'field': 'amount'},
+ 'total_deals': {'operator': 'count', 'field': 'sale_id'}
+ })
+
+ def process_dashboard_data(self, raw_data):
+ """Process raw sales data for dashboard display."""
+ fields = {
+ 'date': {'type': 'date'},
+ 'amount': {'type': 'float'},
+ 'product': {'type': 'char'},
+ 'customer': {'type': 'char'},
+ 'sale_id': {'type': 'integer'}
+ }
+
+ # Filter for current month
+ current_month = get_date_range('this_month')
+
+ # Process trend data
+ trend_data = self.sales_trend.process(raw_data, fields)
+
+ # Aggregate by product
+ product_data = []
+ product_totals = {}
+ for record in raw_data:
+ product = record['product']
+ if product not in product_totals:
+ product_totals[product] = 0
+ product_totals[product] += record['amount']
+
+ for product, revenue in product_totals.items():
+ product_data.append({'product': product, 'revenue': revenue})
+
+ top_products_data = self.top_products.process(product_data, fields)
+
+ # Overall metrics
+ metrics = self.aggregator.aggregate(raw_data)
+
+ return {
+ 'sales_trend': trend_data,
+ 'top_products': top_products_data,
+ 'metrics': metrics,
+ 'tree_config': self.sales_list
+ }
+
+# Usage
+dashboard = SalesDashboard()
+
+sample_data = [
+ {'date': '2023-10-01', 'amount': 1500, 'product': 'Widget A', 'customer': 'Acme Corp', 'sale_id': 1},
+ {'date': '2023-10-02', 'amount': 750, 'product': 'Widget B', 'customer': 'Tech Inc', 'sale_id': 2},
+ {'date': '2023-10-03', 'amount': 2200, 'product': 'Widget A', 'customer': 'Global Ltd', 'sale_id': 3},
+]
+
+dashboard_data = dashboard.process_dashboard_data(sample_data)
+print("Dashboard processed successfully!")
+print("Metrics:", dashboard_data['metrics'])
+```
+
+This comprehensive set of examples demonstrates the full capabilities of Python OOUI across all its major components. Each example is practical and can be adapted for real-world use cases.
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..8a6ac5e
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,75 @@
+# Python OOUI Documentation
+
+Welcome to the Python OOUI documentation! This package is a Python port of ooui.js, providing Object-Oriented User Interface components for data visualization and processing.
+
+## What is Python OOUI?
+
+Python OOUI (Open Object User Interface) is a Python library that provides tools for:
+
+- **Graph Processing**: Create and manipulate various types of charts (line, bar, pie, indicators)
+- **Tree Views**: Parse and process tree-structured data with advanced filtering
+- **Data Helpers**: Utilities for domain parsing, condition evaluation, date handling, and data aggregation
+- **Field Processing**: Handle complex field definitions and relationships
+
+## Key Features
+
+- **Graph Types**: Support for line charts, bar charts, pie charts, and indicator displays
+- **XML Parsing**: Parse XML-based graph and tree definitions
+- **Condition Evaluation**: Advanced condition parsing and evaluation system
+- **Data Aggregation**: Built-in aggregation functions for data analysis
+- **Domain Handling**: Powerful domain parsing with support for complex expressions
+- **Date Utilities**: Comprehensive date and time range processing
+
+## Quick Start
+
+### Installation
+
+```bash
+pip install ooui
+```
+
+### Basic Usage
+
+```python
+from ooui.graph import parse_graph
+from ooui.tree import parse_tree
+
+# Parse a graph from XML
+xml_graph = '''
+
+
+
+
+'''
+graph = parse_graph(xml_graph)
+
+# Parse a tree view
+xml_tree = '''
+
+
+
+
+'''
+tree = parse_tree(xml_tree)
+```
+
+## Documentation Structure
+
+- **[Installation](installation.md)** - Detailed installation and setup instructions
+- **[Usage Guide](usage.md)** - Core concepts and basic usage patterns
+- **[API Reference](api-reference.md)** - Complete API documentation
+- **[Examples](examples.md)** - Practical code examples and use cases
+- **[Advanced Usage](advanced-usage.md)** - Complex scenarios and advanced features
+
+## Getting Help
+
+If you encounter issues or have questions:
+
+1. Check the [Usage Guide](usage.md) for common patterns
+2. Browse the [Examples](examples.md) for practical code samples
+3. Consult the [API Reference](api-reference.md) for detailed method documentation
+4. Review the source code on [GitHub](https://github.com/gisce/python-ooui)
+
+## Contributing
+
+Python OOUI is developed by GISCE. Contributions are welcome! Please visit the [GitHub repository](https://github.com/gisce/python-ooui) for more information.
\ No newline at end of file
diff --git a/docs/installation.md b/docs/installation.md
new file mode 100644
index 0000000..8d86123
--- /dev/null
+++ b/docs/installation.md
@@ -0,0 +1,137 @@
+# Installation Guide
+
+This guide covers the installation and setup of Python OOUI.
+
+## Requirements
+
+Python OOUI requires:
+
+- Python 2.7 or Python 3.x
+- lxml
+- python-dateutil
+- six
+- simpleeval < 0.9.12
+
+## Installation Methods
+
+### Using pip (Recommended)
+
+Install the latest stable version from PyPI:
+
+```bash
+pip install ooui
+```
+
+### Development Installation
+
+For development or to get the latest features:
+
+```bash
+# Clone the repository
+git clone https://github.com/gisce/python-ooui.git
+cd python-ooui
+
+# Install in development mode
+pip install -e .
+
+# Install development dependencies for testing
+pip install -r requirements-dev.txt
+```
+
+## Verifying Installation
+
+To verify your installation is working correctly:
+
+```python
+import ooui
+from ooui.graph import parse_graph
+from ooui.tree import parse_tree
+from ooui.helpers import ConditionParser, Domain
+
+# Test basic imports
+print("Python OOUI installed successfully!")
+```
+
+## Dependencies Explained
+
+### Core Dependencies
+
+- **lxml**: Used for XML parsing and manipulation of graph and tree definitions
+- **python-dateutil**: Provides enhanced date/time parsing and manipulation
+- **six**: Ensures Python 2/3 compatibility
+- **simpleeval**: Safe evaluation of Python expressions in conditions and domains
+
+### Development Dependencies
+
+- **mamba**: Testing framework for behavior-driven development
+- **expects**: Assertion library for testing
+
+## Troubleshooting
+
+### Common Installation Issues
+
+#### lxml Installation Problems
+
+If you encounter issues installing lxml:
+
+**On Ubuntu/Debian:**
+```bash
+sudo apt-get install libxml2-dev libxslt-dev python-dev
+pip install lxml
+```
+
+**On CentOS/RHEL:**
+```bash
+sudo yum install libxml2-devel libxslt-devel python-devel
+pip install lxml
+```
+
+**On macOS:**
+```bash
+# Using Homebrew
+brew install libxml2 libxslt
+pip install lxml
+
+# Or using conda
+conda install lxml
+```
+
+#### Permission Issues
+
+If you encounter permission errors:
+
+```bash
+# Install for current user only
+pip install --user ooui
+
+# Or use virtual environment (recommended)
+python -m venv venv
+source venv/bin/activate # On Windows: venv\Scripts\activate
+pip install ooui
+```
+
+### Virtual Environment Setup (Recommended)
+
+Using a virtual environment is the recommended approach:
+
+```bash
+# Create virtual environment
+python -m venv ooui-env
+
+# Activate it
+source ooui-env/bin/activate # On Windows: ooui-env\Scripts\activate
+
+# Install ooui
+pip install ooui
+
+# When done, deactivate
+deactivate
+```
+
+## Next Steps
+
+Once installed, check out:
+
+- [Usage Guide](usage.md) to learn the basic concepts
+- [Examples](examples.md) for practical code samples
+- [API Reference](api-reference.md) for detailed documentation
\ No newline at end of file
diff --git a/docs/usage.md b/docs/usage.md
new file mode 100644
index 0000000..93ea032
--- /dev/null
+++ b/docs/usage.md
@@ -0,0 +1,292 @@
+# Usage Guide
+
+This guide covers the core concepts and basic usage patterns of Python OOUI.
+
+## Core Concepts
+
+Python OOUI is built around three main components:
+
+1. **Graph Processing** - For creating and manipulating charts and indicators
+2. **Tree Views** - For handling structured data displays
+3. **Helper Utilities** - For data processing, conditions, and domain handling
+
+## Graph Processing
+
+### Graph Types
+
+Python OOUI supports several graph types:
+
+- **line**: Line charts for trend visualization
+- **bar**: Bar charts for comparative data
+- **pie**: Pie charts for proportional data
+- **indicator**: Single-value indicators
+- **indicatorField**: Field-based indicators
+
+### Basic Graph Usage
+
+```python
+from ooui.graph import parse_graph
+
+# Define a line chart
+xml_definition = '''
+
+
+
+
+'''
+
+# Parse the graph
+graph = parse_graph(xml_definition)
+
+# Access graph properties
+print(graph.string) # "Sales Over Time"
+print(graph.type) # "line"
+print(graph.fields) # ['date', 'sales']
+```
+
+### Processing Graph Data
+
+```python
+# Sample data
+data = [
+ {'date': '2023-01-01', 'sales': 1000.0},
+ {'date': '2023-01-02', 'sales': 1200.0},
+ {'date': '2023-01-03', 'sales': 950.0},
+]
+
+# Fields definition (typically from your data model)
+fields = {
+ 'date': {'type': 'date'},
+ 'sales': {'type': 'float'}
+}
+
+# Process the data
+result = graph.process(data, fields)
+print(result) # Processed graph data ready for visualization
+```
+
+### Indicator Graphs
+
+```python
+# Simple indicator
+indicator_xml = '''
+
+
+
+'''
+
+indicator = parse_graph(indicator_xml)
+```
+
+## Tree Views
+
+Tree views handle structured data displays with filtering capabilities.
+
+### Basic Tree Usage
+
+```python
+from ooui.tree import parse_tree
+
+# Define a tree view
+tree_xml = '''
+
+
+
+
+
+'''
+
+# Parse the tree
+tree = parse_tree(tree_xml)
+
+# Access tree properties
+print(tree.string) # "Customer List"
+print(tree.editable) # "top"
+print(len(tree.fields)) # 3
+```
+
+### Tree with Conditional Formatting
+
+```python
+# Tree with colors based on conditions
+tree_with_colors = '''
+
+
+
+
+
+
+'''
+
+tree = parse_tree(tree_with_colors)
+
+# Get fields used in conditions
+conditional_fields = tree.fields_in_conditions
+print(conditional_fields) # {'colors': ['state']}
+```
+
+## Helper Utilities
+
+### Condition Parser
+
+The `ConditionParser` evaluates conditional expressions:
+
+```python
+from ooui.helpers import ConditionParser
+
+# Define conditions
+condition = "red:amount < 100;yellow:amount < 500;green:amount >= 500"
+parser = ConditionParser(condition)
+
+# Check which fields are involved
+print(parser.involved_fields) # ['amount']
+
+# Evaluate conditions with data
+result = parser.eval({'amount': 150})
+print(result) # "red"
+
+result = parser.eval({'amount': 300})
+print(result) # "yellow"
+
+result = parser.eval({'amount': 600})
+print(result) # "green"
+```
+
+### Domain Parsing
+
+The `Domain` class handles complex query expressions:
+
+```python
+from ooui.helpers import Domain
+
+# Simple domain
+domain = Domain("[('active', '=', True), ('age', '>', 18)]")
+parsed = domain.parse()
+print(parsed)
+
+# Domain with variables
+domain_with_vars = Domain("[('date', '>=', start_date), ('user_id', '=', user)]")
+values = {
+ 'start_date': '2023-01-01',
+ 'user': 42
+}
+parsed = domain_with_vars.parse(values)
+```
+
+### Date Utilities
+
+```python
+from ooui.helpers.dates import get_date_range, DateRange
+
+# Create date ranges
+date_range = DateRange('2023-01-01', '2023-12-31')
+print(date_range.start) # datetime object
+print(date_range.end) # datetime object
+
+# Get relative date ranges
+ranges = get_date_range('this_month')
+print(ranges) # Current month start and end dates
+```
+
+### Data Aggregation
+
+```python
+from ooui.helpers.aggregated import Aggregator
+
+# Define aggregation rules
+aggregator = Aggregator({
+ 'sales': {'operator': 'sum', 'field': 'amount'},
+ 'count': {'operator': 'count', 'field': 'id'},
+ 'avg_age': {'operator': 'avg', 'field': 'age'}
+})
+
+# Sample data
+data = [
+ {'amount': 100, 'id': 1, 'age': 25, 'region': 'north'},
+ {'amount': 200, 'id': 2, 'age': 30, 'region': 'north'},
+ {'amount': 150, 'id': 3, 'age': 28, 'region': 'south'},
+]
+
+# Aggregate data
+result = aggregator.aggregate(data, group_by='region')
+print(result)
+# {
+# 'north': {'sales': 300, 'count': 2, 'avg_age': 27.5},
+# 'south': {'sales': 150, 'count': 1, 'avg_age': 28}
+# }
+```
+
+## Advanced Features
+
+### Custom Field Processing
+
+```python
+from ooui.graph.fields import get_value_for_operator
+
+# Apply different operators to field values
+values = [10, 20, 30, 40, 50]
+
+sum_result = get_value_for_operator(values, 'sum') # 150
+avg_result = get_value_for_operator(values, 'avg') # 30
+max_result = get_value_for_operator(values, 'max') # 50
+min_result = get_value_for_operator(values, 'min') # 10
+count_result = get_value_for_operator(values, 'count') # 5
+```
+
+### Boolean Attribute Parsing
+
+```python
+from ooui.helpers import parse_bool_attribute
+
+# Parse various boolean representations
+print(parse_bool_attribute('1')) # True
+print(parse_bool_attribute('true')) # True
+print(parse_bool_attribute('True')) # True
+print(parse_bool_attribute('0')) # False
+print(parse_bool_attribute('false')) # False
+```
+
+### HTML Entity Replacement
+
+```python
+from ooui.helpers import replace_entities
+
+# Clean HTML entities
+text = "Price > $100 & < $200"
+clean_text = replace_entities(text)
+print(clean_text) # "Price > $100 & < $200"
+```
+
+## Best Practices
+
+1. **Always validate XML**: Ensure your XML definitions are well-formed
+2. **Handle missing data**: Check for None values in your data processing
+3. **Use appropriate operators**: Choose the right aggregation operator for your data type
+4. **Test conditions**: Verify conditional expressions with sample data
+5. **Cache parsed objects**: Reuse parsed graphs and trees when possible
+
+## Error Handling
+
+```python
+from ooui.graph import parse_graph
+
+try:
+ # Invalid graph type
+ invalid_xml = ''
+ graph = parse_graph(invalid_xml)
+except ValueError as e:
+ print(f"Error: {e}") # "invalid_type is not a valid graph"
+
+try:
+ # Malformed XML
+ malformed_xml = '' # Missing closing tag
+ graph = parse_graph(malformed_xml)
+except Exception as e:
+ print(f"XML Error: {e}")
+```
+
+## Next Steps
+
+- Check out [Examples](examples.md) for more practical use cases
+- Explore the [API Reference](api-reference.md) for detailed method documentation
+- Learn about [Advanced Usage](advanced-usage.md) for complex scenarios
\ No newline at end of file