Transcript

Filtering data with D2W Philippe Rabier - twitter.com/prabierSophiacom

What is the problem to solve?

Company

EOEntityA

EOEntityB

User

EOEntityC

• Use D2W

• Limit the visibility of the data

• Use conventions to name relationships (for example, any toOne relationship to Company entity, is called company)

• Minimize the code

• Be magic!

The Requirements

Feedback from You ’N Push

First Solution

Working at the editingContext level

modified fetchspec

notificationec factory ec

company

objectsWithFetchSpecification()

creates businessFP

fetchspec

How the qualifier is modified?

public void alterFetchSpecification(final NSNotification aNotification) { EOEditingContext ec = (EOEditingContext) aNotification.object(); if (shouldAddRestrictionQualifier) { Company aCompany = (NOClient) ec.userInfoForKey(NBEditingContextFactory.COMPANY_KEY); final EOFetchSpecification fs = (EOFetchSpecification) aNotification.userInfo().valueForKey(COEditingContext.FETCH_SPEC_KEY); if (aCompany != null && fs != null) { EOEntity aEntity = EOUtilities.entityNamed(ec, fs.entityName());

EOQualifier fsQualifier = fs.qualifier(); if (fsQualifier != null) { NSSet<String> keys = fsQualifier.allQualifierKeys(); for (String aKey : keys) { if (aKey.contains("company")) { shouldAddRestrictionQualifier = false; break; } } } if (shouldAddRestrictionQualifier) { EOQualifier aRestrictionQualifier = clientRestrictionQualifier(aEntity, aClient); if (aRestrictionQualifier != null) { if (fsQualifier != null) fsQualifier = new EOAndQualifier(new NSArray<EOQualifier>(new EOQualifier[] {fsQualifier, aRestrictionQualifier})); else fsQualifier = aRestrictionQualifier; fs.setQualifier(fsQualifier); } } } } }

How the qualifier is modified?

public EOQualifier companyRestrictionQualifier(final EOEntity entity, final Company company) {

EOQualifier aQualifier = null; if (entity.name().equals(Company.Keys.ENTITY_NAME)) aQualifier = new EOKeyValueQualifier(Company.Keys.NAME, EOQualifier.QualifierOperatorEqual, company.name()); else if (entity.relationshipNamed("company") != null) aQualifier = new EOKeyValueQualifier("company", EOQualifier.QualifierOperatorEqual, company); else if (entity.relationshipNamed("entityB") != null) aQualifier = new EOKeyValueQualifier("entityB.company", EOQualifier.QualifierOperatorEqual, client); else if (entity.relationshipNamed("entityC") != null) ...;

if (log.isDebugEnabled()) log.debug("method: qualifier: " + aQualifier); return aQualifier; }

It works great

but there is a little problem

it’s too low level

An Example of Problem

public void validateForSave() throws ValidationException { super.validateForSave(); ERXEOControlUtilities.validateUniquenessOf(this, NOUser.Keys.LOGIN); ERXEOControlUtilities.validateUniquenessOf(this, NOUser.Keys.EMAIL); }

public void validateForSave() throws ValidationException { super.validateForSave(); editingContext().setUserInfoForKey(Boolean.FALSE, NBEditingContextFactory.NO_RESTRICTION_QUAL_KEY); ERXEOControlUtilities.validateUniquenessOf(this, NOUser.Keys.LOGIN); ERXEOControlUtilities.validateUniquenessOf(this, NOUser.Keys.EMAIL); editingContext().setUserInfoForKey(Boolean.TRUE, NBEditingContextFactory.NO_RESTRICTION_QUAL_KEY); }

Second Solution

• Displaying a list

• Using a query component

• Using ERD2WEditToManyRelationship component

• Using ERD2WEditToOneRelationship component

When should we filter?

• Modify the NavigationController object

• Change the data source

Displaying a list

public WOComponent listPageForEntityName(final String entityName) { ListPageInterface newListPageInterface = D2W.factory().listPageForEntityNamed(entityName, session()); EODatabaseDataSource dataSource = new EODatabaseDataSource(ERXEC.newEditingContext(), entityName); EOEntity entity = ERXEOAccessUtilities.entityNamed(null, entityName); EOQualifier auxQual = NBBusinessLogicPrincipal.getSharedInstance().clientRestrictionQualifier(entity, ((Session)session()).getCompany());

dataSource.setAuxiliaryQualifier(auxQual);

newListPageInterface.setDataSource(dataSource); return (WOComponent) newListPageInterface; }

• Use a query delegate

• Override the method queryDataSource(ERD2WQueryPage sender)

Using a query component

{ author = 100; class = "com.webobjects.directtoweb.Rule"; lhs = { class = "com.webobjects.eocontrol.EOKeyValueQualifier"; key = pageConfiguration; selectorName = isEqualTo; value = QueryMyEntity; }; rhs = { class = "er.directtoweb.ERDDelayedObjectCreationAssignment"; keyPath = queryDataSourceDelegate; value = "ca.wowodc.very.util.pascal.delegate.SomeOneElse"; };}

• Maybe subclass the 2 component is the best solution

• Use restrictingFetchSpecification key. If all fetchspec have the same name, it’s possible to build a generic rule.

• Need to be modified to add the possibility to set a binding to the fetchspec

• Maybe a lot of pain to create many fetchspec in the EOModel

EditRelationship components

How the qualifier is modified?

public Object restrictedChoiceList() { String restrictedChoiceKey=(String)d2wContext().valueForKey("restrictedChoiceKey"); if( restrictedChoiceKey!=null && restrictedChoiceKey.length()>0 ) return valueForKeyPath(restrictedChoiceKey); String fetchSpecName=(String)d2wContext().valueForKey("restrictingFetchSpecification"); if(fetchSpecName != null) { EORelationship relationship = ERXUtilities.relationshipWithObjectAndKeyPath(object(), (String)d2wContext().valueForKey("propertyKey")); if(relationship != null) return EOUtilities.objectsWithFetchSpecificationAndBindings(object().editingContext(), relationship.destinationEntity().name(),fetchSpecName,null); } return null; }

@prabier

Follow me!

Q&ATBD

top related