ViewBuilder #PL-2048

This commit is contained in:
Yuriy Artamonov 2013-04-20 10:08:41 +00:00
parent 925710cf5a
commit a0e4261b14
6 changed files with 313 additions and 0 deletions

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.util
import com.haulmont.cuba.core.CubaTestCase
import com.haulmont.cuba.core.global.View
import com.haulmont.cuba.core.util.ViewBuilder
/**
* @author artamonov
* @version $Id$
*/
class ViewBuilderTest extends CubaTestCase {
ViewBuilder builder
@Override
protected void setUp() throws Exception {
super.setUp()
builder = new ViewBuilder()
}
public void testSimpleViewDefinition() {
View view1 = builder.view(class: 'com.haulmont.cuba.security.entity.Group',
name: 'group.edit.test', extends: 'group.browse') {
property(name: 'constraints', view: '_local')
property(name: 'sessionAttributes', view: '_local')
}
assertNotNull(view1)
assertEquals(4, view1.properties.size())
}
public void testDeepViewDefinition() {
View view2 = builder.view(entity: 'sec$Group', name: 'group.edit.test', extends: 'group.browse') {
property(name: 'constraints', view: 'group.browse')
property(name: 'sessionAttributes', view: '_local')
property(name: 'parent', view: '_local') {
property(name: 'parent') {
property(name: 'name')
}
}
}
assertNotNull(view2)
assertEquals(4, view2.properties.size())
assertEquals(2, view2.getProperty('parent').getView().properties.size())
assertEquals(1, view2.getProperty('parent').getView().getProperty('parent').getView().properties.size())
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.core.util
import com.haulmont.bali.util.ReflectionHelper
import com.haulmont.cuba.core.global.AppBeans
import com.haulmont.cuba.core.global.Metadata
import com.haulmont.cuba.core.global.View
import com.haulmont.cuba.core.global.ViewRepository
import org.apache.commons.lang.StringUtils
/**
* Simple Groovy builder for view definitions
*
* @author artamonov
* @version $Id$
*/
class ViewBuilder {
private Metadata metadata = AppBeans.get(Metadata.class)
private ViewRepository viewRepository = AppBeans.get(ViewRepository.class)
private View createView(ViewNode viewNode) {
String entity = viewNode.entity
com.haulmont.chile.core.model.MetaClass metaClass
if (StringUtils.isBlank(entity)) {
String className = viewNode.className
if (StringUtils.isBlank(className))
throw new IllegalStateException('Invalid view definition: no \'entity\' or \'class\' attribute')
Class entityClass = ReflectionHelper.getClass(className)
metaClass = metadata.getClassNN(entityClass)
} else {
metaClass = metadata.getClassNN(entity)
}
String viewName = viewNode.name
String extendsView = viewNode.extendsView
if (viewNode.systemProperties == null)
viewNode.systemProperties = false;
View view
if (StringUtils.isNotBlank(extendsView)) {
View ancestorView = viewRepository.getView(metaClass, extendsView)
boolean includeSystemProperties = viewNode.systemProperties == null ?
ancestorView.isIncludeSystemProperties() : viewNode.systemProperties
view = new View(ancestorView, metaClass.getJavaClass(), viewName, includeSystemProperties)
} else {
view = new View(metaClass.getJavaClass(), viewName, viewNode.systemProperties)
}
for (ViewPropertyNode propertyNode : viewNode.viewProperties) {
createPropertyView(view, propertyNode)
}
return view
}
private void createPropertyView(View view, ViewPropertyNode viewPropertyNode) {
final com.haulmont.chile.core.model.MetaClass metaClass = metadata.getClassNN(view.getEntityClass())
String propertyName = viewPropertyNode.name
com.haulmont.chile.core.model.MetaProperty metaProperty = metaClass.getProperty(propertyName)
if (metaProperty == null) {
throw new IllegalStateException(
String.format("View ${metaClass.name}/${view.name} definition error: property $propertyName doesn't exists")
)
}
View refView = null
com.haulmont.chile.core.model.MetaClass refMetaClass
com.haulmont.chile.core.model.Range range = metaProperty.getRange()
if (range == null) {
throw new IllegalStateException("Cannot find range for meta property ${metaProperty}");
}
boolean inlineView = !viewPropertyNode.viewProperties.isEmpty()
if (StringUtils.isNotBlank(viewPropertyNode.view) && !inlineView) {
if (!range.isClass()) {
throw new IllegalStateException(
String.format("View ${metaClass.name}/${view.name} definition error: property $propertyName is not an entity")
);
}
refMetaClass = range.asClass()
refView = viewRepository.findView(refMetaClass, viewPropertyNode.name)
}
if (range.isClass() && refView == null && inlineView) {
String extendsView = viewPropertyNode.view
if (StringUtils.isBlank(extendsView)) {
refView = new View(range.asClass().getJavaClass())
} else {
refMetaClass = range.asClass()
View ancestorView = viewRepository.getView(refMetaClass, extendsView)
refView = new View(ancestorView, range.asClass().getJavaClass(), "", true)
}
for (ViewPropertyNode childPropertyNode : viewPropertyNode.viewProperties) {
createPropertyView(refView, childPropertyNode)
}
}
if (viewPropertyNode.lazy == null)
viewPropertyNode.lazy = false
view.addProperty(propertyName, refView, viewPropertyNode.lazy)
}
View view(Map attributes, Closure definition) {
ViewNode viewNode = new ViewNodeBuilder().view(attributes, definition)
return createView(viewNode)
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.core.util
/**
* @author artamonov
* @version $Id$
*/
class ViewNode {
String className
String entity
String name
String extendsView
Boolean systemProperties
List<ViewPropertyNode> viewProperties = []
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.core.util
import javax.naming.OperationNotSupportedException
/**
* @author artamonov
* @version $Id$
*/
@PackageScope
class ViewNodeBuilder extends BuilderSupport {
@Override
protected void setParent(Object parent, Object child) {
if (child != null)
parent.viewProperties.add(child)
}
@Override
protected Object createNode(Object name) {
throw new OperationNotSupportedException()
}
@Override
protected Object createNode(Object name, Object value) {
throw new OperationNotSupportedException()
}
@Override
protected Object createNode(Object name, Map attributes) {
if ('view' == name) {
return new ViewNode(
name: attributes['name'],
entity: attributes['entity'],
className: attributes['class'],
extendsView: attributes['extends'],
systemProperties: attributes['systemProperties']
)
}
if ('property' == name) {
return new ViewPropertyNode(
name: attributes['name'],
view: attributes['view'],
lazy: attributes['lazy']
)
}
throw new OperationNotSupportedException()
}
@Override
protected Object createNode(Object name, Map attributes, Object value) {
throw new OperationNotSupportedException()
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.core.util
/**
* @author artamonov
* @version $Id$
*/
class ViewPropertyNode {
String name
String view
Boolean lazy
List<ViewPropertyNode> viewProperties = []
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2013 Haulmont Technology Ltd. All Rights Reserved.
* Haulmont Technology proprietary and confidential.
* Use is subject to license terms.
*/
package com.haulmont.cuba.core.util
import junit.framework.TestCase
/**
* @author artamonov
* @version $Id$
*/
class ViewNodeBuilderTest extends TestCase {
public void testSimpleView() {
def builder = new ViewNodeBuilder()
def viewDefinition = builder.view(entity: 'sec$UserSubstitution', extends: 'user.edit') {
property(name: 'substitutedUser') {
property(name: 'name')
property(name: 'login')
}
property(name: 'startDate')
property(name: 'endDate')
}
assertNotNull(viewDefinition)
}
}