refactoring field processing: class FieldInstance for processing and collecting state information

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1971 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-08-30 07:53:09 +00:00
parent 18ea13f7b8
commit 90377b06b9
5 changed files with 61 additions and 54 deletions

View file

@ -10,4 +10,6 @@
<adapter factory="cybertools.composer.schema.instance.ClientInstanceEditor" <adapter factory="cybertools.composer.schema.instance.ClientInstanceEditor"
name="editor" /> name="editor" />
<adapter factory="cybertools.composer.schema.field.FieldInstance" />
</configure> </configure>

View file

@ -23,9 +23,10 @@ $Id$
""" """
from zope.interface import implements from zope.interface import implements
from zope.component import adapts
from cybertools.composer.base import Component from cybertools.composer.base import Component
from cybertools.composer.schema.interfaces import IField, IFieldState from cybertools.composer.schema.interfaces import IField, IFieldInstance
from cybertools.composer.schema.schema import formErrors from cybertools.composer.schema.schema import formErrors
from cybertools.util.format import toStr, toUnicode from cybertools.util.format import toStr, toUnicode
@ -53,6 +54,19 @@ class Field(Component):
def getTitleValue(self): def getTitleValue(self):
return self.title or self.name return self.title or self.name
class FieldInstance(object):
implements(IFieldInstance)
adapts(IField)
def __init__(self, context):
self.context = context
self.name = self.__name__ = context.name
self.errors = []
self.severity = 0
self.change = None
def marshall(self, value): def marshall(self, value):
return value return value
#return toStr(value) #return toStr(value)
@ -64,23 +78,11 @@ class Field(Component):
def unmarshall(self, strValue): def unmarshall(self, strValue):
return toUnicode(strValue) or u'' return toUnicode(strValue) or u''
def validateValue(self, value): def validate(self, value):
errors = [] errors = []
severity = 0 severity = 0
if not value and self.required: if not value and self.context.required:
error = formErrors['required_missing'] error = formErrors['required_missing']
errors.append(error) self.errors.append(error)
severity = error.severity self.severity = error.severity
return FieldState(self.name, errors, severity)
class FieldState(object):
implements(IFieldState)
def __init__(self, name, errors=[], severity=0, change=None):
self.name = self.__name__ = name
self.errors = errors
self.severity = severity
self.change = change

View file

@ -28,7 +28,7 @@ from zope.interface import implements
from cybertools.composer.instance import Instance from cybertools.composer.instance import Instance
from cybertools.composer.interfaces import IInstance from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import IClient from cybertools.composer.schema.interfaces import IClient, IFieldInstance
from cybertools.composer.schema.schema import FormState from cybertools.composer.schema.schema import FormState
@ -75,9 +75,10 @@ class ClientInstance(object):
values = attrs.setdefault(self.aspect, {}) values = attrs.setdefault(self.aspect, {})
if template is not None: if template is not None:
for f in template.fields: for f in template.fields:
fi = IFieldInstance(f)
name = f.name name = f.name
value = values.get(name, u'') value = values.get(name, u'')
value = mode == 'view' and f.display(value) or f.marshall(value) value = mode == 'view' and fi.display(value) or fi.marshall(value)
result[name] = value result[name] = value
result['__name__'] = self.context.__name__ result['__name__'] = self.context.__name__
return result return result
@ -103,23 +104,25 @@ class ClientInstanceEditor(ClientInstance):
setattr(self.context, self.attrsName, attrs) setattr(self.context, self.attrsName, attrs)
values = attrs.setdefault(self.aspect, OOBTree()) values = attrs.setdefault(self.aspect, OOBTree())
for f in template.fields: for f in template.fields:
#fi = IFieldInstance(f)
name = f.name name = f.name
fieldState = formState.fieldStates[name] fi = formState.fieldInstances[name]
value = f.unmarshall(data.get(name)) value = fi.unmarshall(data.get(name))
if name in data: if name in data:
oldValue = values.get(name) oldValue = values.get(name)
if value != oldValue: if value != oldValue:
values[name] = value values[name] = value
fieldState.change = (oldValue, value) fi.change = (oldValue, value)
formState.changed = True formState.changed = True
return formState return formState
def validate(self, data): def validate(self, data):
formState = FormState() formState = FormState()
for f in self.template.fields: for f in self.template.fields:
value = f.unmarshall(data.get(f.name)) fi = IFieldInstance(f)
fieldState = f.validateValue(value) value = fi.unmarshall(data.get(f.name))
formState.fieldStates.append(fieldState) fi.validate(value)
formState.severity = max(formState.severity, fieldState.severity) formState.fieldInstances.append(fi)
formState.severity = max(formState.severity, fi.severity)
return formState return formState

View file

@ -99,32 +99,12 @@ class IField(IComponent):
'(only for type textarea)'), '(only for type textarea)'),
default=3, default=3,
required=False,) required=False,)
# validator = schema.Text(),
# marshaller = schema.Text(),
def marshallValue(value):
""" Return a string (possibly unicode) representation of the
value given that may be used for editing.
"""
def displayValue(value):
""" Return a string (possibly unicode) representation of the
value given that may be used for presentation.
"""
def unmarshallValue(strValue):
""" Return the internal (real) value corresponding to the string
value given.
"""
def validateValue(value):
""" Check if the value given is valid. Return an object implementing
IFieldState.
"""
class IFieldState(Interface): class IFieldInstance(Interface):
""" Represents the state of a field used for editing. """ An adapter for checking and converting data values coming
from or being displayed on an external system (like a browser form).
It also keeps information on the processing state.
""" """
name = Attribute('Field name.') name = Attribute('Field name.')
@ -133,15 +113,35 @@ class IFieldState(Interface):
severity = Attribute("An integer giving a state or error " severity = Attribute("An integer giving a state or error "
"code, 0 meaning 'OK'.") "code, 0 meaning 'OK'.")
def marshall(value):
""" Return a string (possibly unicode) representation of the
value given that may be used for editing.
"""
def display(value):
""" Return a string (possibly unicode) representation of the
value given that may be used for presentation.
"""
def unmarshall(strValue):
""" Return the internal (real) value corresponding to the string
value given.
"""
def validate(value):
""" Check if the value given is valid. Return an object implementing
IFieldState.
"""
class IFormState(Interface): class IFormState(Interface):
""" Represents the state of all fields when editing. """ Represents the state of all fields when editing.
""" """
fieldStates = Attribute('A mapping ``{fieldName: fieldState, ...}``.') fieldStates = Attribute('A mapping ``{fieldName: fieldState, ...}``.')
changed = Attribute('True if one of the fields has been changed or False.') changed = Attribute('True if one of the fields has been changed')
severity = Attribute("An integer giving an overall state or error " severity = Attribute("An integer giving an overall state or error "
"code, typically the maximum of the field states' " "code, typically the maximum of the field instances' "
"severities.") "severities.")

View file

@ -64,8 +64,8 @@ class FormState(object):
implements(IFormState) implements(IFormState)
def __init__(self, fieldStates=[], changed=False, severity=0): def __init__(self, fieldInstances=[], changed=False, severity=0):
self.fieldStates = Jeep(fieldStates) self.fieldInstances = Jeep(fieldInstances)
self.changed = changed self.changed = changed
self.severity = severity self.severity = severity