org.netbeans.modeler.specification.model.document.property.ElementPropertySet Maven / Gradle / Ivy
Go to download
Jeddict is an open source Jakarta EE application development platform that accelerates developers productivity and simplifies development tasks of creating complex entity relationship models.
/**
* Copyright 2013-2022 Gaurav Gupta
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.netbeans.modeler.specification.model.document.property;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.netbeans.modeler.config.element.Attribute;
import org.netbeans.modeler.config.element.Element;
import org.netbeans.modeler.config.element.ElementConfig;
import org.netbeans.modeler.config.element.ElementConfigFactory;
import org.netbeans.modeler.config.element.Group;
import org.netbeans.modeler.config.element.ModelerSheetProperty;
import org.netbeans.modeler.core.ModelerFile;
import org.netbeans.modeler.properties.enumtype.EnumComboBoxResolver;
import org.netbeans.modeler.properties.type.Embedded;
import org.netbeans.modeler.properties.type.Enumy;
import org.netbeans.modeler.specification.model.document.ITextElement;
import static org.netbeans.modeler.specification.model.document.property.PropertySetUtil.createPropertyChangeHandler;
import static org.netbeans.modeler.specification.model.document.property.PropertySetUtil.createPropertyVisibilityHandler;
import static org.netbeans.modeler.specification.model.document.property.PropertySetUtil.elementValueChanged;
import org.netbeans.modeler.specification.model.document.widget.IBaseElementWidget;
import org.netbeans.modeler.widget.properties.generic.ElementCustomPropertySupport;
import org.netbeans.modeler.widget.properties.generic.ElementPropertySupport;
import org.netbeans.modeler.widget.properties.handler.PropertyChangeListener;
import org.netbeans.modeler.widget.properties.handler.PropertyVisibilityHandler;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
public class ElementPropertySet {
private ModelerFile modelerFile;
private final ElementConfig elementConfig;
private Sheet sheet;
private Map set = new HashMap<>();
public ElementPropertySet(ModelerFile modelerFile, Sheet sheet) {
this.modelerFile = modelerFile;
this.sheet = sheet;
this.elementConfig = modelerFile.getModelerDiagramModel().getElementConfigFactory().getElementConfig();;
}
public void createGroup(Group group) {
set.put(group, sheet.createPropertiesSet());
set.get(group).setName(group.getId());// Sheet.Set : name is required work as key [otherwise set is replaced]
}
public void deleteGroup(String id) {
Group group = getElementConfigGroup(id);
set.remove(group);
}
public void clearGroup(String id) {
Group group = getElementConfigGroup(id);
if(set.get(group)!=null){
for(Node.Property> property : set.get(group).getProperties()){
set.get(group).remove(property.getName());
}
}
}
public void clearGroups() {
for(Sheet.Set setTmp : set.values()){
Arrays.fill( setTmp.getProperties(), null );
}
set.clear();
}
private Map> preOrderedPropeties = new LinkedHashMap<>();
public synchronized void put(String id, Node.Property> p, boolean replace) {
LinkedList properties = preOrderedPropeties.get(id);
if(properties==null){
preOrderedPropeties.put(id, properties = new LinkedList<>());
}
properties.add(new SheetProperty(p,replace));
}
public void executeProperties(){
for(Entry> entry : preOrderedPropeties.entrySet()){
LinkedList propertyList = entry.getValue();
//Prepare hashmap container
Map> filterContainerMap= new LinkedHashMap<>();
propertyList.forEach(p -> {
if (filterContainerMap.get(p.getProperty().getName()) == null) {
PropertyLinkedList propertyLinkedList = new PropertyLinkedList<>();
propertyLinkedList.addFirst(p);
filterContainerMap.put(p.getProperty().getName(), propertyLinkedList);
} else {
filterContainerMap.get(p.getProperty().getName()).addLast(p);
}
});
propertyList.forEach(p -> {
if(p.getProperty() instanceof ModelerSheetProperty){
ModelerSheetProperty msp = (ModelerSheetProperty)p.getProperty();
if(msp.getAfter()!=null){
PropertyLinkedList linklistA = filterContainerMap.get(msp.getAfter());
PropertyLinkedList linklistB = filterContainerMap.get(p.getProperty().getName());
if(linklistA==null){
System.out.println("Invalid after type : " + msp.getAfter());
}
if(linklistA!=null && linklistA!=linklistB){
linklistA.addLast(linklistB.getHead());
}
}
if(msp.getBefore()!=null){
PropertyLinkedList linklistB = filterContainerMap.get(p.getProperty().getName());
PropertyLinkedList linklistA = filterContainerMap.get(msp.getBefore());
if(linklistA==null){
System.out.println("Invalid before type : " + msp.getBefore());
}
if(linklistA!=null && linklistA!=linklistB){
linklistB.addLast(linklistA.getHead());
}
}
}
});
for (Entry> filterEntry : filterContainerMap.entrySet()) {
PropertyLinkedList propertyLinkedList = filterEntry.getValue();
if (propertyLinkedList.getHead().prev == null) {
PropertyLinkedList.Node node = propertyLinkedList.getHead();
while (node != null) {
putProperty(entry.getKey(), node.element.getProperty(), node.element.isReplace());
node = node.next;
}
}
}
}
preOrderedPropeties.clear();
}
public synchronized Node.Property> putProperty(String id, Node.Property> p, boolean replace) {
Group group = getElementConfigGroup(id);
if (set.get(group) == null) {
createGroup(group);
setGroupDisplayName(id, group.getName());
}
if (replace && set.get(group).get(p.getName()) != null) {
set.get(group).remove(p.getName());
}
return set.get(group).put(p);
}
private Group getElementConfigGroup(String id){
Group group = elementConfig.getGroup(id);
if (group == null) {
throw new RuntimeException("Group Id : <" + id + "> not found in element config");
}
return group;
}
public synchronized void put(String id, Node.Property> p) {
put(id, p, false);
}
public void setGroupDisplayName(String id, String displayName) {
Group group = getElementConfigGroup(id);
set.get(group).setDisplayName(displayName);
}
/**
* @return the sheet
*/
public Sheet getSheet() {
return sheet;
}
/**
* @param sheet the sheet to set
*/
public void setSheet(Sheet sheet) {
this.sheet = sheet;
}
/**
* @return the set
*/
public Sheet.Set getGroup(String id) {
Group group = getElementConfigGroup(id);
return set.get(group);
}
public Set getGroupKey() {
return set.keySet().stream().map(Group::getName).collect(toSet());
}
public List getGroups() {
return set.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(entry -> entry.getValue()).collect(toList());
}
/**
* @return the modelerFile
*/
public ModelerFile getModelerFile() {
return modelerFile;
}
/**
* @param modelerFile the modelerFile to set
*/
public void setModelerFile(ModelerFile modelerFile) {
this.modelerFile = modelerFile;
}
public void createPropertySet(IBaseElementWidget baseElementWidget, final Object object) {
createPropertySet(null,null,baseElementWidget, object, null, null, true, false);
}
public void createPropertySet(IBaseElementWidget baseElementWidget, final Object object,
final Map propertyChangeHandlers) {
createPropertySet(null,null,baseElementWidget, object, propertyChangeHandlers, null, true, false);
}
/*
* Override attributes groupId
*/
public void createPropertySet(String groupId, IBaseElementWidget baseElementWidget, final Object object,
final Map propertyChangeHandlers) {
createPropertySet(groupId,null,baseElementWidget, object, propertyChangeHandlers, null, true, false);
}
/*
* Filter using category
category used when object have more than one child of same type
*/
public void createPropertySet(String groupId,String category, IBaseElementWidget baseElementWidget, final Object object) {
createPropertySet(groupId,category,baseElementWidget, object, null, null, true, false);
}
public void createPropertySet(String groupId,String category, IBaseElementWidget baseElementWidget, final Object object,
final Map propertyChangeHandlers) {
createPropertySet(groupId,category,baseElementWidget, object, propertyChangeHandlers, null, true, false);
}
public void createPropertySet(IBaseElementWidget baseElementWidget, final Object object,
final Map propertyChangeHandlers,
final Map propertyVisiblityHandlers) {
createPropertySet(null,null,baseElementWidget, object, propertyChangeHandlers, propertyVisiblityHandlers, true, false);
}
public void createPropertySet(IBaseElementWidget baseElementWidget, final Object object,
final Map propertyChangeHandlers, boolean inherit) {
createPropertySet(null,null,baseElementWidget, object, propertyChangeHandlers, null, true, false);
}
/**
* Replace Property Start
*
* @param baseElementWidget
* @param object
* @param propertyChangeHandlers *
*/
public void replacePropertySet(IBaseElementWidget baseElementWidget, final Object object,
final Map propertyChangeHandlers) {
createPropertySet(null,null,baseElementWidget, object, propertyChangeHandlers, null, true, true);
}
private void createPropertySet(String groupId,String category, IBaseElementWidget baseElementWidget, final Object object, final Map propertyChangeHandlers, final Map propertyVisiblityHandlers, boolean inherit, boolean replaceProperty) {
ElementConfigFactory elementConfigFactory = modelerFile.getModelerDiagramModel().getElementConfigFactory();
if (inherit) {
for (Element element : elementConfigFactory.getElements(category,object.getClass())) {
createPropertySetInternal(groupId,baseElementWidget, object, element, propertyChangeHandlers, propertyVisiblityHandlers, replaceProperty);
}
} else {
Element element = elementConfigFactory.getElement(category,object.getClass());
if (element != null) {
createPropertySetInternal(groupId,baseElementWidget, object, element, propertyChangeHandlers, propertyVisiblityHandlers, replaceProperty);
}
}
}
private void createPropertySetInternal(String groupId,final IBaseElementWidget baseElementWidget, final Object object, Element element, final Map propertyChangeHandlers, final Map propertyVisiblityHandlers, boolean replaceProperty) {
try {
if (element != null) {
for (final Attribute attribute : element.getAttributes()) {
String attributeGroupId = groupId;
if (attributeGroupId == null) {
attributeGroupId = attribute.getGroupId();
}
if (attribute.getClassType() == ITextElement.class) {
final String name = attribute.getName();
final ITextElement expression = (ITextElement) PropertyUtils.getProperty(object, name);//return must not be null//(TExpression) PropertyUtils.getProperty(object, id) == null ? new TExpression() : (TExpression) PropertyUtils.getProperty(object, id);
this.put(attributeGroupId, new ElementCustomPropertySupport(this.getModelerFile(), expression, String.class, attribute.getId(),"content",
attribute.getDisplayName(), attribute.getShortDescription(), (PropertyChangeListener) (oldValue, value) -> {
if (expression.getContent() == null || expression.getContent().isEmpty()) {
try {
PropertyUtils.setProperty(object, name, null);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
Exceptions.printStackTrace(ex);
}
}
if (propertyChangeHandlers != null && propertyChangeHandlers.get(name) != null) {
propertyChangeHandlers.get(name).changePerformed(oldValue, value);
}
if (attribute.isRefreshOnChange()) {
baseElementWidget.refreshProperties();
}
}, propertyVisiblityHandlers == null ? null : propertyVisiblityHandlers.get(attribute.getId())), replaceProperty);
} else if (Enumy.class.isAssignableFrom(attribute.getClassType())) {
EnumComboBoxResolver resolver = Lookup.getDefault().lookup(EnumComboBoxResolver.class);
this.put(attributeGroupId,resolver.getPropertySupport(modelerFile, attribute, baseElementWidget, object, propertyChangeHandlers));
} else if (Embedded.class.isAssignableFrom(attribute.getClassType())) {
if(attribute.getGroupId() != null){
groupId = attribute.getGroupId();
}
//in embedded id is used as category
this.createPropertySet(groupId, attribute.getId(), baseElementWidget, PropertyUtils.getSimpleProperty(object, attribute.getName()), propertyChangeHandlers, propertyVisiblityHandlers, true, replaceProperty);
} else {
if (attribute.isReadOnly()) {
String value = BeanUtils.getProperty(object, attribute.getName());
if (value == null) {
BeanUtils.setProperty(object, attribute.getName(), attribute.getValue());
}
this.put(attributeGroupId, new ElementPropertySupport(object, attribute.getFieldGetter(), null, attribute), replaceProperty);
} else {
PropertyVisibilityHandler propertyVisibilityHandler = propertyVisiblityHandlers == null ? null : propertyVisiblityHandlers.get(attribute.getId());
Serializable visibilityExpression = attribute.getVisibilityExpression();
if (propertyVisibilityHandler == null && visibilityExpression != null) {
propertyVisibilityHandler = createPropertyVisibilityHandler(modelerFile, baseElementWidget, object, visibilityExpression);
}
if (propertyChangeHandlers != null && propertyChangeHandlers.get(attribute.getId()) == null && attribute.getOnChangeEvent() != null && !attribute.getOnChangeEvent().trim().isEmpty()) {
propertyChangeHandlers.put(attribute.getId(), createPropertyChangeHandler(modelerFile, baseElementWidget, object, attribute.getChangeListenerExpression()));
}
this.put(attributeGroupId, new ElementCustomPropertySupport(this.getModelerFile(), object, attribute, (PropertyChangeListener