work in progress: relation fields/widgets
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@3165 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
		
							parent
							
								
									b28c81d9b4
								
							
						
					
					
						commit
						edd2b3fbe4
					
				
					 12 changed files with 232 additions and 76 deletions
				
			
		|  | @ -39,7 +39,7 @@ class TargetAction(Action): | ||||||
|     viewTitle = '' |     viewTitle = '' | ||||||
|     addParams = {} |     addParams = {} | ||||||
| 
 | 
 | ||||||
|     #@Lazy |     @Lazy | ||||||
|     def url(self): |     def url(self): | ||||||
|         if self.page is None:   # how could this happen? |         if self.page is None:   # how could this happen? | ||||||
|             baseUrl = self.view.virtualTargetUrl |             baseUrl = self.view.virtualTargetUrl | ||||||
|  |  | ||||||
|  | @ -57,6 +57,7 @@ from loops.browser.concept import ConceptRelationView | ||||||
| from loops.i18n.browser import I18NView | from loops.i18n.browser import I18NView | ||||||
| from loops.query import ConceptQuery, IQueryConcept | from loops.query import ConceptQuery, IQueryConcept | ||||||
| from loops.resource import Resource | from loops.resource import Resource | ||||||
|  | from loops.schema.field import relation_macros | ||||||
| from loops.type import ITypeConcept | from loops.type import ITypeConcept | ||||||
| from loops import util | from loops import util | ||||||
| from loops.util import _ | from loops.util import _ | ||||||
|  | @ -113,6 +114,7 @@ class ObjectForm(NodeView): | ||||||
|         # replace HTML edit widget with Dojo Editor |         # replace HTML edit widget with Dojo Editor | ||||||
|         renderers['input_html'] = self.template.macros['input_html'] |         renderers['input_html'] = self.template.macros['input_html'] | ||||||
|         renderers['input_grid'] = grid_macros.macros['input_grid'] |         renderers['input_grid'] = grid_macros.macros['input_grid'] | ||||||
|  |         renderers['input_relationset'] = relation_macros.macros['input_relationset'] | ||||||
|         return renderers |         return renderers | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|  | @ -358,6 +360,7 @@ class CreateConceptForm(CreateObjectForm): | ||||||
|         if ti is None: |         if ti is None: | ||||||
|             return c |             return c | ||||||
|         ad = ti(c) |         ad = ti(c) | ||||||
|  |         ad.__is_dummy__ = True | ||||||
|         return ad |         return ad | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|  | @ -394,7 +397,8 @@ class CreateConceptPage(CreateConceptForm): | ||||||
| 
 | 
 | ||||||
|     @Lazy |     @Lazy | ||||||
|     def nextUrl(self): |     def nextUrl(self): | ||||||
|         return self.nodeView.getUrlForTarget(self.context) |         #return self.nodeView.getUrlForTarget(self.context) | ||||||
|  |         return self.getUrlForTarget(self.context) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class InnerForm(CreateObjectForm): | class InnerForm(CreateObjectForm): | ||||||
|  |  | ||||||
|  | @ -143,6 +143,17 @@ function addConceptAssignment(prefix, suffix) { | ||||||
|     node.appendChild(tr); |     node.appendChild(tr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | function addRelation(fieldName) { | ||||||
|  |     valuesNode = dojo.byId(fieldName + '_values'); | ||||||
|  |     widget = dijit.byId(fieldName + '_search'); | ||||||
|  |     token = widget.getValue(); | ||||||
|  |     title = widget.getDisplayedValue(); | ||||||
|  |     ih = '<input type="checkbox" name="' + name + ':list" value="' + token + '" checked> <span>' + title + '</span>'; | ||||||
|  |     newNode = document.createElement('div'); | ||||||
|  |     newNode.innerHTML = ih; | ||||||
|  |     valuesNode.appendChild(newNode); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| function validate() { | function validate() { | ||||||
|     //var form = dijit.byId('dialog_form');
 |     //var form = dijit.byId('dialog_form');
 | ||||||
|     var form = dojo.byId('dialog_form'); |     var form = dojo.byId('dialog_form'); | ||||||
|  |  | ||||||
|  | @ -96,6 +96,8 @@ class AdapterBase(object): | ||||||
|     _noexportAttributes = () |     _noexportAttributes = () | ||||||
|     _textIndexAttributes = () |     _textIndexAttributes = () | ||||||
| 
 | 
 | ||||||
|  |     __is_dummy__ = False | ||||||
|  | 
 | ||||||
|     languageInfo = None |     languageInfo = None | ||||||
| 
 | 
 | ||||||
|     def __init__(self, context): |     def __init__(self, context): | ||||||
|  | @ -107,7 +109,7 @@ class AdapterBase(object): | ||||||
|         return getattr(self.context, '_' + attr, None) |         return getattr(self.context, '_' + attr, None) | ||||||
| 
 | 
 | ||||||
|     def __setattr__(self, attr, value): |     def __setattr__(self, attr, value): | ||||||
|         if attr in self._adapterAttributes: |         if attr.startswith('__') or attr in self._adapterAttributes: | ||||||
|             try: |             try: | ||||||
|                 object.__setattr__(self, attr, value) |                 object.__setattr__(self, attr, value) | ||||||
|             except AttributeError: |             except AttributeError: | ||||||
|  | @ -332,6 +334,8 @@ class ParentRelationSet(RelationSet): | ||||||
|         self.context.deassignParent(related, [self.predicate]) |         self.context.deassignParent(related, [self.predicate]) | ||||||
| 
 | 
 | ||||||
|     def __iter__(self): |     def __iter__(self): | ||||||
|  |         if self.adapted.__is_dummy__: | ||||||
|  |             return | ||||||
|         for c in self.context.getParents([self.predicate]): |         for c in self.context.getParents([self.predicate]): | ||||||
|             yield adapted(c, langInfo=self.langInfo) |             yield adapted(c, langInfo=self.langInfo) | ||||||
| 
 | 
 | ||||||
|  | @ -350,6 +354,8 @@ class ChildRelationSet(RelationSet): | ||||||
|         self.context.deassignChild(related, [self.predicate]) |         self.context.deassignChild(related, [self.predicate]) | ||||||
| 
 | 
 | ||||||
|     def __iter__(self): |     def __iter__(self): | ||||||
|  |         if self.adapted.__is_dummy__: | ||||||
|  |             return | ||||||
|         for c in self.context.getChildren([self.predicate]): |         for c in self.context.getChildren([self.predicate]): | ||||||
|             yield adapted(c, langInfo=self.langInfo) |             yield adapted(c, langInfo=self.langInfo) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -346,13 +346,15 @@ | ||||||
|            name="fileupload" /> |            name="fileupload" /> | ||||||
|   <adapter factory="cybertools.composer.schema.grid.field.GridFieldInstance" |   <adapter factory="cybertools.composer.schema.grid.field.GridFieldInstance" | ||||||
|            name="grid" /> |            name="grid" /> | ||||||
|  |   <adapter factory="loops.schema.field.RelationSetFieldInstance" | ||||||
|  |            name="relationset" /> | ||||||
| 
 | 
 | ||||||
|   <adapter factory="cybertools.composer.schema.factory.SchemaFactory" /> |   <adapter factory="cybertools.composer.schema.factory.SchemaFactory" /> | ||||||
|   <adapter factory="loops.schema.ResourceSchemaFactory" /> |   <adapter factory="loops.schema.factory.ResourceSchemaFactory" /> | ||||||
|   <adapter factory="loops.schema.ResourceSchemaFactory" |   <adapter factory="loops.schema.factory.ResourceSchemaFactory" | ||||||
|            for="loops.interfaces.IResource" /> |            for="loops.interfaces.IResource" /> | ||||||
|   <adapter factory="loops.schema.FileSchemaFactory" /> |   <adapter factory="loops.schema.factory.FileSchemaFactory" /> | ||||||
|   <adapter factory="loops.schema.NoteSchemaFactory" /> |   <adapter factory="loops.schema.factory.NoteSchemaFactory" /> | ||||||
| 
 | 
 | ||||||
|   <adapter factory="loops.setup.SetupManager" /> |   <adapter factory="loops.setup.SetupManager" /> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								schema/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								schema/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | """ | ||||||
|  | $Id$ | ||||||
|  | """ | ||||||
|  | 
 | ||||||
							
								
								
									
										76
									
								
								schema/base.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								schema/base.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | ||||||
|  | # | ||||||
|  | #  Copyright (c) 2009 Helmut Merz helmutm@cy55.de | ||||||
|  | # | ||||||
|  | #  This program is free software; you can redistribute it and/or modify | ||||||
|  | #  it under the terms of the GNU General Public License as published by | ||||||
|  | #  the Free Software Foundation; either version 2 of the License, or | ||||||
|  | #  (at your option) any later version. | ||||||
|  | # | ||||||
|  | #  This program is distributed in the hope that it will be useful, | ||||||
|  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | #  GNU General Public License for more details. | ||||||
|  | # | ||||||
|  | #  You should have received a copy of the GNU General Public License | ||||||
|  | #  along with this program; if not, write to the Free Software | ||||||
|  | #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | Specialized field definitions. | ||||||
|  | 
 | ||||||
|  | $Id$ | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | from zope.component import adapts | ||||||
|  | from zope.interface import Attribute, implements | ||||||
|  | from zope.schema import Choice, List | ||||||
|  | from zope.schema.interfaces import IChoice, IList | ||||||
|  | 
 | ||||||
|  | from cybertools.composer.schema.interfaces import FieldType | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class IRelation(IChoice): | ||||||
|  |     """ An object addressed via a single relation. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     target_types = Attribute('A list of names that denote types of ' | ||||||
|  |                 'loops objects (typically concept types) that may be used as ' | ||||||
|  |                 'targets for the relation.') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class IRelationSet(IList): | ||||||
|  |     """ A collection of objects addressed via a set of relations. | ||||||
|  | 
 | ||||||
|  |         Despite its name, the collection may have a predefined order. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     target_types = Attribute('A list of names that denote types of ' | ||||||
|  |                 'loops objects (typically concept types) that may be used as ' | ||||||
|  |                 'targets for the relations.') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Relation(Choice): | ||||||
|  | 
 | ||||||
|  |     implements(IRelation) | ||||||
|  | 
 | ||||||
|  |     __typeInfo__ = ('relation',) | ||||||
|  | 
 | ||||||
|  |     def __init__(self, *args, **kw): | ||||||
|  |         self.target_types = kw.pop('target_types') | ||||||
|  |         super(Relation, self).__init__(*args, **kw) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class RelationSet(List): | ||||||
|  | 
 | ||||||
|  |     implements(IRelationSet) | ||||||
|  | 
 | ||||||
|  |     __typeInfo__ = ('relationset', | ||||||
|  |                     FieldType('relationset', 'relationset', | ||||||
|  |                               u'A field representing a sequence of related objects.', | ||||||
|  |                               instanceName='relationset')) | ||||||
|  | 
 | ||||||
|  |     def __init__(self, *args, **kw): | ||||||
|  |         self.target_types = kw.pop('target_types') | ||||||
|  |         super(RelationSet, self).__init__(*args, **kw) | ||||||
|  | 
 | ||||||
|  | @ -17,64 +17,16 @@ | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
| """ | """ | ||||||
| Specialized fields and schema factories | Specialized fields factories. | ||||||
| 
 | 
 | ||||||
| $Id$ | $Id$ | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| from zope.component import adapts | from zope.component import adapts | ||||||
| from zope.interface import Attribute, implements |  | ||||||
| from zope.schema import Choice, List |  | ||||||
| from zope.schema.interfaces import IChoice, IList |  | ||||||
| 
 | 
 | ||||||
| from cybertools.composer.schema.factory import SchemaFactory | from cybertools.composer.schema.factory import SchemaFactory | ||||||
| from loops.interfaces import IResourceAdapter, IFile, INote | from loops.interfaces import IResourceAdapter, IFile, INote | ||||||
| 
 | 
 | ||||||
| # fields |  | ||||||
| 
 |  | ||||||
| class IRelation(IChoice): |  | ||||||
|     """ An object addressed via a single relation. |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     target_types = Attribute('A list of names that denote types of ' |  | ||||||
|                 'loops objects (typically concept types) that may be used as ' |  | ||||||
|                 'targets for the relation.') |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class IRelationSet(IList): |  | ||||||
|     """ A collection of objects addressed via a set of relations. |  | ||||||
| 
 |  | ||||||
|         Despite its name, the collection may have a predefined order. |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     target_types = Attribute('A list of names that denote types of ' |  | ||||||
|                 'loops objects (typically concept types) that may be used as ' |  | ||||||
|                 'targets for the relations.') |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Relation(Choice): |  | ||||||
| 
 |  | ||||||
|     implements(IRelation) |  | ||||||
| 
 |  | ||||||
|     __typeInfo = ('relation',) |  | ||||||
| 
 |  | ||||||
|     def __init__(self, *args, **kw): |  | ||||||
|         self.target_types = kw.pop('target_types') |  | ||||||
|         super(Relation, self).__init__(*args, **kw) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class RelationSet(List): |  | ||||||
| 
 |  | ||||||
|     implements(IRelationSet) |  | ||||||
| 
 |  | ||||||
|     __typeInfo = ('relationset',) |  | ||||||
| 
 |  | ||||||
|     def __init__(self, *args, **kw): |  | ||||||
|         self.target_types = kw.pop('target_types') |  | ||||||
|         super(RelationSet, self).__init__(*args, **kw) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # schema factories |  | ||||||
| 
 | 
 | ||||||
| class ResourceSchemaFactory(SchemaFactory): | class ResourceSchemaFactory(SchemaFactory): | ||||||
| 
 | 
 | ||||||
							
								
								
									
										64
									
								
								schema/field.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								schema/field.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | ||||||
|  | # | ||||||
|  | #  Copyright (c) 2008 Helmut Merz helmutm@cy55.de | ||||||
|  | # | ||||||
|  | #  This program is free software; you can redistribute it and/or modify | ||||||
|  | #  it under the terms of the GNU General Public License as published by | ||||||
|  | #  the Free Software Foundation; either version 2 of the License, or | ||||||
|  | #  (at your option) any later version. | ||||||
|  | # | ||||||
|  | #  This program is distributed in the hope that it will be useful, | ||||||
|  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | #  GNU General Public License for more details. | ||||||
|  | # | ||||||
|  | #  You should have received a copy of the GNU General Public License | ||||||
|  | #  along with this program; if not, write to the Free Software | ||||||
|  | #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | Field and field instance classes for grids. | ||||||
|  | 
 | ||||||
|  | $Id$ | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | from zope import component | ||||||
|  | from zope.component import adapts | ||||||
|  | from zope.interface import implements | ||||||
|  | from zope.app.pagetemplate import ViewPageTemplateFile | ||||||
|  | from zope.cachedescriptors.property import Lazy | ||||||
|  | import zope.schema | ||||||
|  | 
 | ||||||
|  | from cybertools.composer.schema.factory import createField | ||||||
|  | from cybertools.composer.schema.field import ListFieldInstance | ||||||
|  | from cybertools.composer.schema.interfaces import IField, IFieldInstance | ||||||
|  | from cybertools.composer.schema.interfaces import fieldTypes, undefined | ||||||
|  | from cybertools.util.format import toStr, toUnicode | ||||||
|  | from cybertools.util import json | ||||||
|  | from loops import util | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | relation_macros = ViewPageTemplateFile('relation_macros.pt') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class RelationSetFieldInstance(ListFieldInstance): | ||||||
|  | 
 | ||||||
|  |     def marshall(self, value): | ||||||
|  |         return [dict(title=v.title, uid=util.getUidForObject(v.context)) | ||||||
|  |                 for v in value] | ||||||
|  | 
 | ||||||
|  |     def display(self, value): | ||||||
|  |         return value | ||||||
|  | 
 | ||||||
|  |     def unmarshall(self, value): | ||||||
|  |         return value | ||||||
|  | 
 | ||||||
|  |     @Lazy | ||||||
|  |     def typesParams(self): | ||||||
|  |         result = [] | ||||||
|  |         types = self.context.target_types | ||||||
|  |         for t in types: | ||||||
|  |             result.append('searchType=loops:concept:%s' % t) | ||||||
|  |         if result: | ||||||
|  |             return '?' + '&'.join(result) | ||||||
|  |         return '' | ||||||
							
								
								
									
										31
									
								
								schema/relation_macros.pt
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								schema/relation_macros.pt
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US" | ||||||
|  |       i18n:domain="loops"> | ||||||
|  | <body> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | <metal:textline define-macro="input_relationset" | ||||||
|  |                 tal:define="fieldInstance field/getFieldInstance; | ||||||
|  |                             types fieldInstance/typesParams"> | ||||||
|  |     <div dojoType="dojox.data.QueryReadStore" jsId="conceptSearch" | ||||||
|  |          tal:attributes="url string:listConceptsForComboBox.js$types; | ||||||
|  |                          jsId string:${name}_search_store" > | ||||||
|  |     </div> | ||||||
|  |     <div tal:attributes="id string:${name}_values"> | ||||||
|  |       <div tal:repeat="obj data/?name"> | ||||||
|  |         <input type="checkbox" checked | ||||||
|  |                tal:attributes="name string:$name:list; | ||||||
|  |                                value obj/uid" /> | ||||||
|  |         <span tal:content="obj/title" /> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |     <input dojoType="dijit.form.FilteringSelect" | ||||||
|  |            autoComplete="False" labelAttr="label" | ||||||
|  |            tal:attributes="store string:${name}_search_store; | ||||||
|  |                            name string:${name}_search; | ||||||
|  |                            id string:${name}_search; | ||||||
|  |                            onChange string:addRelation('$name')" /> | ||||||
|  | </metal:textline> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | @ -98,14 +98,17 @@ class Search(BaseView): | ||||||
|         title = request.get('name') |         title = request.get('name') | ||||||
|         if title == '*': |         if title == '*': | ||||||
|             title = None |             title = None | ||||||
|         type = request.get('searchType') |         types = request.get('searchType') | ||||||
|         data = [] |         data = [] | ||||||
|         if title or type: |         if title or types: | ||||||
|             if title is not None: |             if title is not None: | ||||||
|                 title = title.replace('(', ' ').replace(')', ' ').replace(' -', ' ') |                 title = title.replace('(', ' ').replace(')', ' ').replace(' -', ' ') | ||||||
|                 #title = title.split(' ', 1)[0] |                 #title = title.split(' ', 1)[0] | ||||||
|             if not type: |             if not types: | ||||||
|                 type = 'loops:concept:*' |                 types = ['loops:concept:*'] | ||||||
|  |             if not isinstance(types, (list, tuple)): | ||||||
|  |                 types = [types] | ||||||
|  |             for type in types: | ||||||
|                 result = ConceptQuery(self).query(title=title or None, type=type, |                 result = ConceptQuery(self).query(title=title or None, type=type, | ||||||
|                                                   exclude=('system',)) |                                                   exclude=('system',)) | ||||||
|                 for o in result: |                 for o in result: | ||||||
|  |  | ||||||
|  | @ -61,7 +61,9 @@ from loops.expert.concept import QueryConcept | ||||||
| from loops.resource import Resource, FileAdapter, TextDocumentAdapter | from loops.resource import Resource, FileAdapter, TextDocumentAdapter | ||||||
| from loops.resource import Document, MediaAsset | from loops.resource import Document, MediaAsset | ||||||
| from loops.resource import IndexAttributes as ResourceIndexAttributes | from loops.resource import IndexAttributes as ResourceIndexAttributes | ||||||
| from loops.schema import ResourceSchemaFactory, FileSchemaFactory, NoteSchemaFactory | from loops.schema.factory import ResourceSchemaFactory, FileSchemaFactory, \ | ||||||
|  |                                  NoteSchemaFactory | ||||||
|  | from loops.schema.field import RelationSetFieldInstance | ||||||
| from loops.security.common import grantAcquiredSecurity, revokeAcquiredSecurity | from loops.security.common import grantAcquiredSecurity, revokeAcquiredSecurity | ||||||
| from zope.security.management import setSecurityPolicy | from zope.security.management import setSecurityPolicy | ||||||
| from loops.security.policy import LoopsSecurityPolicy | from loops.security.policy import LoopsSecurityPolicy | ||||||
|  | @ -141,6 +143,7 @@ class TestSite(object): | ||||||
|         component.provideAdapter(BooleanFieldInstance, name='boolean') |         component.provideAdapter(BooleanFieldInstance, name='boolean') | ||||||
|         component.provideAdapter(ListFieldInstance, name='list') |         component.provideAdapter(ListFieldInstance, name='list') | ||||||
|         component.provideAdapter(FileUploadFieldInstance, name='fileupload') |         component.provideAdapter(FileUploadFieldInstance, name='fileupload') | ||||||
|  |         component.provideAdapter(RelationSetFieldInstance, name='relationset') | ||||||
|         component.provideAdapter(SchemaFactory) |         component.provideAdapter(SchemaFactory) | ||||||
|         component.provideAdapter(ResourceSchemaFactory) |         component.provideAdapter(ResourceSchemaFactory) | ||||||
|         component.provideAdapter(FileSchemaFactory) |         component.provideAdapter(FileSchemaFactory) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 helmutm
						helmutm