Java tutorial
/* * Copyright 2008-2012 the original author or authors. * * 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.broadleafcommerce.openadmin.client.datasource.dynamic.module; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.client.rpc.AsyncCallback; import com.gwtincubator.security.exception.ApplicationSecurityException; import com.smartgwt.client.data.Criteria; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; import com.smartgwt.client.data.DataSource; import com.smartgwt.client.data.DataSourceField; import com.smartgwt.client.data.Record; import com.smartgwt.client.data.SortSpecifier; import com.smartgwt.client.data.fields.DataSourceBooleanField; import com.smartgwt.client.data.fields.DataSourceDateTimeField; import com.smartgwt.client.data.fields.DataSourceEnumField; import com.smartgwt.client.data.fields.DataSourceFloatField; import com.smartgwt.client.data.fields.DataSourceImageField; import com.smartgwt.client.data.fields.DataSourceIntegerField; import com.smartgwt.client.data.fields.DataSourcePasswordField; import com.smartgwt.client.data.fields.DataSourceTextField; import com.smartgwt.client.types.FieldType; import com.smartgwt.client.types.SortDirection; import com.smartgwt.client.util.JSON; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.form.fields.ComboBoxItem; import com.smartgwt.client.widgets.form.validator.Validator; import com.smartgwt.client.widgets.grid.ListGrid; import com.smartgwt.client.widgets.tree.TreeNode; import org.broadleafcommerce.common.presentation.client.OperationType; import org.broadleafcommerce.common.presentation.client.PersistencePerspectiveItemType; import org.broadleafcommerce.common.presentation.client.SupportedFieldType; import org.broadleafcommerce.common.presentation.client.VisibilityEnum; import org.broadleafcommerce.openadmin.client.BLCMain; import org.broadleafcommerce.openadmin.client.datasource.LookupMetadata; import org.broadleafcommerce.openadmin.client.datasource.dynamic.AbstractDynamicDataSource; import org.broadleafcommerce.openadmin.client.datasource.dynamic.BatchManager; import org.broadleafcommerce.openadmin.client.datasource.dynamic.BatchOperationType; import org.broadleafcommerce.openadmin.client.datasource.dynamic.BatchPackage; import org.broadleafcommerce.openadmin.client.datasource.dynamic.operation.EntityOperationType; import org.broadleafcommerce.openadmin.client.datasource.dynamic.operation.EntityServiceAsyncCallback; import org.broadleafcommerce.openadmin.client.dto.AdornedTargetCollectionMetadata; import org.broadleafcommerce.openadmin.client.dto.BasicCollectionMetadata; import org.broadleafcommerce.openadmin.client.dto.BasicFieldMetadata; import org.broadleafcommerce.openadmin.client.dto.ClassMetadata; import org.broadleafcommerce.openadmin.client.dto.CriteriaTransferObject; import org.broadleafcommerce.openadmin.client.dto.DynamicResultSet; import org.broadleafcommerce.openadmin.client.dto.Entity; import org.broadleafcommerce.openadmin.client.dto.FilterAndSortCriteria; import org.broadleafcommerce.openadmin.client.dto.ForeignKey; import org.broadleafcommerce.openadmin.client.dto.MapMetadata; import org.broadleafcommerce.openadmin.client.dto.MergedPropertyType; import org.broadleafcommerce.openadmin.client.dto.PersistencePackage; import org.broadleafcommerce.openadmin.client.dto.PersistencePerspective; import org.broadleafcommerce.openadmin.client.dto.Property; import org.broadleafcommerce.openadmin.client.dto.visitor.MetadataVisitorAdapter; import org.broadleafcommerce.openadmin.client.presenter.entity.DynamicEntityPresenter; import org.broadleafcommerce.openadmin.client.service.AbstractCallback; import org.broadleafcommerce.openadmin.client.service.DynamicEntityServiceAsync; import org.broadleafcommerce.openadmin.client.setup.AsyncCallbackAdapter; import org.broadleafcommerce.openadmin.client.setup.PresenterSequenceSetupManager; import org.broadleafcommerce.openadmin.client.validation.ValidationFactoryManager; import org.broadleafcommerce.openadmin.client.view.dynamic.form.FormHiddenEnum; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * * @author jfischer * */ public class BasicClientEntityModule implements DataSourceModule { protected final DateTimeFormat formatter = DateTimeFormat.getFormat("yyyy.MM.dd HH:mm:ss Z"); protected ForeignKey currentForeignKey; protected AbstractDynamicDataSource dataSource; protected String linkedValue; protected DynamicEntityServiceAsync service; protected final String ceilingEntityFullyQualifiedClassname; protected final String fetchTypeFullyQualifiedClassname; protected PersistencePerspective persistencePerspective; protected Long loadLevelCount = 0L; public BasicClientEntityModule(String ceilingEntityFullyQualifiedClassname, PersistencePerspective persistencePerspective, DynamicEntityServiceAsync service) { this(ceilingEntityFullyQualifiedClassname, null, persistencePerspective, service); } public BasicClientEntityModule(String ceilingEntityFullyQualifiedClassname, String fetchTypeFullyQualifiedClassname, PersistencePerspective persistencePerspective, DynamicEntityServiceAsync service) { this.service = service; this.ceilingEntityFullyQualifiedClassname = ceilingEntityFullyQualifiedClassname; this.fetchTypeFullyQualifiedClassname = fetchTypeFullyQualifiedClassname; this.persistencePerspective = persistencePerspective; } /** * Transforms the given <tt>request</tt> into * {@link CriteriaTransferObject} instance. * <p> * We are doing this because we can apply seamless * CTO-to-criteria conversions back on the server. */ @Override public CriteriaTransferObject getCto(DSRequest request) { CriteriaTransferObject cto = new CriteriaTransferObject(); // paging if (request.getStartRow() != null) { cto.setFirstResult(request.getStartRow()); if (request.getEndRow() != null) { cto.setMaxResults(request.getEndRow() - request.getStartRow()); } } try { // sort SortSpecifier[] sortBy = request.getSortBy(); if (sortBy != null && sortBy.length > 0) { String sortPropertyId = sortBy[0].getField(); boolean sortAscending = sortBy[0].getSortDirection().equals(SortDirection.ASCENDING); FilterAndSortCriteria sortCriteria = cto.get(sortPropertyId); sortCriteria.setSortAscending(sortAscending); } } catch (Exception e) { //do nothing GWT.log("WARN: Unable to set sort criteria because of an exception.", e); } Criteria criteria = request.getCriteria(); String jsObj = JSON.encode(criteria.getJsObj()); // filter Map filterData = criteria.getValues(); Set<String> filterFieldNames = filterData.keySet(); for (String fieldName : filterFieldNames) { if (!fieldName.equals("_constructor") && !fieldName.equals("operator")) { if (!fieldName.equals("criteria")) { FilterAndSortCriteria filterCriteria = cto.get(fieldName); Object filterValue = filterData.get(fieldName); String filterString = null; if (filterValue != null) { filterString = filterValue.toString(); } String fieldTypeVal = null; DataSourceField field = dataSource.getField(fieldName); if (field != null) { fieldTypeVal = field.getAttribute("fieldType"); } SupportedFieldType fieldType = fieldTypeVal == null ? SupportedFieldType.STRING : SupportedFieldType.valueOf(fieldTypeVal); if (fieldType != null) { switch (fieldType) { case DECIMAL: processFilterValueClause(filterCriteria, filterString); break; case INTEGER: processFilterValueClause(filterCriteria, filterString); break; case MONEY: processFilterValueClause(filterCriteria, filterString); break; default: filterCriteria .setFilterValue(dataSource.stripDuplicateAllowSpecialCharacters(filterString)); break; } } else { filterCriteria .setFilterValue(dataSource.stripDuplicateAllowSpecialCharacters(filterString)); } } else { JSONValue value = JSONParser.parse(jsObj); JSONObject criteriaObj = value.isObject(); JSONArray criteriaArray = criteriaObj.get("criteria").isArray(); buildCriteria(criteriaArray, cto); } } } if (getCurrentForeignKey() != null) { FilterAndSortCriteria filterCriteria = cto.get(getCurrentForeignKey().getManyToField()); filterCriteria.setFilterValue(getCurrentForeignKey().getCurrentValue()); } return cto; } protected void processFilterValueClause(FilterAndSortCriteria filterCriteria, String filterString) { String filterVal = dataSource.stripDuplicateAllowSpecialCharacters(filterString); int pos = filterVal.indexOf("-"); String decimalSeparator = LocaleInfo.getCurrentLocale().getNumberConstants().decimalSeparator(); if (pos > 0) { //TODO this method does not deal well with negative values that may be entered into the filter field. String filterValue1 = filterVal.substring(0, pos).trim(); int decimalPos = filterValue1.indexOf(decimalSeparator); if (decimalPos >= 0) { filterValue1 = filterValue1.substring(0, decimalPos) + "." + filterValue1.substring(decimalPos + 1, filterValue1.length()); } String filterValue2 = filterVal.substring(pos + 1, filterVal.length()).trim(); decimalPos = filterValue2.indexOf(decimalSeparator); if (decimalPos >= 0) { filterValue2 = filterValue2.substring(0, decimalPos) + "." + filterValue2.substring(decimalPos + 1, filterValue2.length()); } filterCriteria.setFilterValues(filterValue1, filterValue2); } else { int decimalPos = filterVal.indexOf(decimalSeparator); if (decimalPos >= 0) { filterVal = filterVal.substring(0, decimalPos) + "." + filterVal.substring(decimalPos + 1, filterVal.length()); } filterCriteria.setFilterValue(filterVal); } } public ForeignKey getCurrentForeignKey() { return currentForeignKey; } public void setCurrentForeignKey(ForeignKey currentForeignKey) { this.currentForeignKey = currentForeignKey; } @Override public String getLinkedValue() { return linkedValue; } @Override public void setLinkedValue(String linkedValue) { this.linkedValue = linkedValue; } protected void buildCriteria(JSONArray criteriaArray, CriteriaTransferObject cto) { if (criteriaArray != null) { for (int i = 0; i <= criteriaArray.size() - 1; i++) { JSONObject itemObj = criteriaArray.get(i).isObject(); if (itemObj != null) { JSONValue val = itemObj.get("fieldName"); if (val == null) { JSONArray array = itemObj.get("criteria").isArray(); buildCriteria(array, cto); } else { FilterAndSortCriteria filterCriteria = cto.get(val.isString().stringValue()); String[] items = filterCriteria.getFilterValues(); String[] newItems = new String[items.length + 1]; int j = 0; for (String item : items) { newItems[j] = item; j++; } JSONValue value = itemObj.get("value"); newItems[j] = value.toString(); newItems[j] = newItems[j].replaceAll("\"", ""); String fieldTypeVal = null; DataSourceField field = dataSource.getField(val.isString().stringValue()); if (field != null) { fieldTypeVal = field.getAttribute("fieldType"); } SupportedFieldType fieldType = fieldTypeVal == null ? SupportedFieldType.STRING : SupportedFieldType.valueOf(fieldTypeVal); if (fieldType != null) { switch (fieldType) { case DECIMAL: processFilterValueClause(filterCriteria, newItems[j]); break; case INTEGER: processFilterValueClause(filterCriteria, newItems[j]); break; case MONEY: processFilterValueClause(filterCriteria, newItems[j]); break; case DATE: if (newItems.length > 1) { for (int x = 0; x < newItems.length; x++) { newItems[x] = updateMinutesFromDateFilter(newItems[x], x); } filterCriteria.setFilterValues(newItems); } else { String[] dateItems = new String[2]; JSONValue operator = itemObj.get("operator"); String op = operator.isString().stringValue(); if (op.startsWith("greater")) { dateItems[0] = newItems[0]; dateItems[1] = null; } else { dateItems[0] = null; dateItems[1] = newItems[0]; } for (int x = 0; x < dateItems.length; x++) { dateItems[x] = updateMinutesFromDateFilter(dateItems[x], x); } filterCriteria.setFilterValues(dateItems); } break; default: filterCriteria.setFilterValues(newItems); break; } } else { filterCriteria.setFilterValues(newItems); } } } } } } protected String updateMinutesFromDateFilter(String originalDateString, int position) { // Default the timezone to the server's current timezone String timezone = DateTimeFormat.getFormat("Z").format(new Date()); if (originalDateString != null) { int pos = originalDateString.indexOf("T"); // Possibly adjust the timezone for the date the user selected Date date = DateTimeFormat.getFormat("yyyy-MM-dd").parse(originalDateString.substring(0, pos)); if (date != null) { timezone = DateTimeFormat.getFormat("Z").format(date); } switch (position) { case 0: if (pos >= 0) { return originalDateString.substring(0, pos) + "T00:00:00" + " " + timezone; } break; default: if (pos >= 0) { return originalDateString.substring(0, pos) + "T23:59:00" + " " + timezone; } break; } } return originalDateString == null ? null : originalDateString + " " + timezone; } @Override public boolean isCompatible(OperationType operationType) { return OperationType.BASIC.equals(operationType) || OperationType.NONDESTRUCTIVEREMOVE.equals(operationType); } @Override public void executeFetch(final String requestId, final DSRequest request, final DSResponse response, final String[] customCriteria, final AsyncCallback<DataSource> cb) { BLCMain.NON_MODAL_PROGRESS.startProgress(); if (request.getCriteria() != null && request.getCriteria().getAttribute("blc.fetch.from.cache") != null) { Criteria currentCriteria = request.getCriteria(); String cacheFetchId = currentCriteria.getAttribute("blc.fetch.from.cache"); Record cachedData = dataSource.getAddedRecord(); if (cachedData != null) { Record[] recordList = new Record[] { cachedData }; response.setData(recordList); response.setTotalRows(1); if (cb != null) { cb.onSuccess(dataSource); } dataSource.processResponse(requestId, response); } else { throw new RuntimeException("Unable to find cached record with id: " + cacheFetchId); } } else { CriteriaTransferObject cto = getCto(request); service.fetch( new PersistencePackage(ceilingEntityFullyQualifiedClassname, fetchTypeFullyQualifiedClassname, null, persistencePerspective, customCriteria, BLCMain.csrfToken), cto, new EntityServiceAsyncCallback<DynamicResultSet>(EntityOperationType.FETCH, requestId, request, response, dataSource) { @Override public void onSuccess(DynamicResultSet result) { super.onSuccess(result); TreeNode[] recordList = buildRecords(result, null); response.setData(recordList); response.setTotalRows(result.getTotalRecords()); if (cb != null) { cb.onSuccess(dataSource); } dataSource.processResponse(requestId, response); } @Override protected void onSecurityException(ApplicationSecurityException exception) { super.onSecurityException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onOtherException(Throwable exception) { super.onOtherException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onError(EntityOperationType opType, String requestId, DSRequest request, DSResponse response, Throwable caught) { super.onError(opType, requestId, request, response, caught); if (cb != null) { cb.onFailure(caught); } } }); } } @Override public void executeAdd(final String requestId, final DSRequest request, final DSResponse response, final String[] customCriteria, final AsyncCallback<DataSource> cb) { BLCMain.NON_MODAL_PROGRESS.startProgress(); JavaScriptObject data = request.getData(); TreeNode record = new TreeNode(data); Entity entity = buildEntity(record, request); service.add( new PersistencePackage(ceilingEntityFullyQualifiedClassname, entity, persistencePerspective, customCriteria, BLCMain.csrfToken), new EntityServiceAsyncCallback<Entity>(EntityOperationType.ADD, requestId, request, response, dataSource) { @Override public void onSuccess(Entity result) { super.onSuccess(result); if (processResult(result, requestId, response, dataSource)) { TreeNode record = (TreeNode) buildRecord(result, false); TreeNode[] recordList = new TreeNode[] { record }; response.setData(recordList); if (cb != null) { cb.onSuccess(dataSource); } dataSource.processResponse(requestId, response); } } @Override protected void onSecurityException(ApplicationSecurityException exception) { super.onSecurityException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onOtherException(Throwable exception) { super.onOtherException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onError(EntityOperationType opType, String requestId, DSRequest request, DSResponse response, Throwable caught) { super.onError(opType, requestId, request, response, caught); if (cb != null) { cb.onFailure(caught); } } }); } @Override public void executeUpdate(final String requestId, final DSRequest request, final DSResponse response, final String[] customCriteria, final AsyncCallback<DataSource> cb) { BLCMain.NON_MODAL_PROGRESS.startProgress(); JavaScriptObject data = request.getData(); final TreeNode record = new TreeNode(data); Entity entity = buildEntity(record, request); String componentId = request.getComponentId(); if (componentId != null) { if (entity.getType() == null) { String[] type = ((ListGrid) Canvas.getById(componentId)).getSelectedRecord() .getAttributeAsStringArray("_type"); entity.setType(type); } } service.update( new PersistencePackage(ceilingEntityFullyQualifiedClassname, entity, persistencePerspective, customCriteria, BLCMain.csrfToken), new EntityServiceAsyncCallback<Entity>(EntityOperationType.UPDATE, requestId, request, response, dataSource) { @Override public void onSuccess(Entity result) { super.onSuccess(null); if (processResult(result, requestId, response, dataSource)) { TreeNode record = (TreeNode) buildRecord(result, false); TreeNode[] recordList = new TreeNode[] { record }; response.setData(recordList); if (cb != null) { cb.onSuccess(dataSource); } dataSource.processResponse(requestId, response); } } @Override protected void onSecurityException(ApplicationSecurityException exception) { super.onSecurityException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onOtherException(Throwable exception) { super.onOtherException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onError(EntityOperationType opType, String requestId, DSRequest request, DSResponse response, Throwable caught) { super.onError(opType, requestId, request, response, caught); if (cb != null) { cb.onFailure(caught); } } }); } @Override public void executeRemove(final String requestId, final DSRequest request, final DSResponse response, final String[] customCriteria, final AsyncCallback<DataSource> cb) { BLCMain.NON_MODAL_PROGRESS.startProgress(); JavaScriptObject data = request.getData(); TreeNode record = new TreeNode(data); Entity entity = buildEntity(record, request); String componentId = request.getComponentId(); if (componentId != null) { if (entity.getType() == null) { String[] type = ((ListGrid) Canvas.getById(componentId)).getSelectedRecord() .getAttributeAsStringArray("_type"); entity.setType(type); } } service.remove( new PersistencePackage(ceilingEntityFullyQualifiedClassname, entity, persistencePerspective, customCriteria, BLCMain.csrfToken), new EntityServiceAsyncCallback<Void>(EntityOperationType.REMOVE, requestId, request, response, dataSource) { @Override public void onSuccess(Void item) { super.onSuccess(null); if (cb != null) { cb.onSuccess(dataSource); } dataSource.processResponse(requestId, response); } @Override protected void onSecurityException(ApplicationSecurityException exception) { super.onSecurityException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onOtherException(Throwable exception) { super.onOtherException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onError(EntityOperationType opType, String requestId, DSRequest request, DSResponse response, Throwable caught) { super.onError(opType, requestId, request, response, caught); if (cb != null) { cb.onFailure(caught); } } }); } @Override public Record buildRecord(Entity entity, Boolean updateId) { TreeNode record = new TreeNode(); return updateRecord(entity, record, updateId); } @Override public Record updateRecord(Entity entity, Record record, Boolean updateId) { String id = entity.findProperty(dataSource.getPrimaryKeyFieldName()).getValue(); if (updateId) { id = id + "_^_" + loadLevelCount; loadLevelCount++; } for (Property property : entity.getProperties()) { String attributeName = property.getName(); if (dataSource.getField(attributeName) != null) { if (property.getValue() != null && dataSource.getField(attributeName).getType().equals(FieldType.DATETIME)) { if (property.getValue() != null && !property.getValue().equals("null")) { record.setAttribute(attributeName, formatter.parse(property.getValue())); } } else if (dataSource.getField(attributeName).getType().equals(FieldType.BOOLEAN)) { if (property.getValue() == null) { record.setAttribute(attributeName, false); } else { String lower = property.getValue().toLowerCase(); if (lower.equals("y") || lower.equals("yes") || lower.equals("true") || lower.equals("1")) { record.setAttribute(attributeName, true); } else { record.setAttribute(attributeName, false); } } } else if (dataSource.getField(attributeName).getAttributeAsString("fieldType") .equals(SupportedFieldType.PASSWORD.toString())) { String propertyValue = property.getValue(); record.setAttribute(attributeName, propertyValue); if (dataSource.getField(attributeName).getValidators() != null && dataSource.getField(attributeName).getValidators().length > 0) { for (Validator validator : dataSource.getField(attributeName).getValidators()) { if (validator.getAttribute("type").equals("matchesField") && validator.getAttribute("otherField") != null) { record.setAttribute(validator.getAttribute("otherField"), propertyValue); break; } } } } else if (property.getMetadata() != null && ((BasicFieldMetadata) property.getMetadata()).getFieldType() != null && ((BasicFieldMetadata) property.getMetadata()).getFieldType() .equals(SupportedFieldType.FOREIGN_KEY)) { record.setAttribute(attributeName, linkedValue); } else if (property.getValue() != null && dataSource.getField(attributeName).getType().equals(FieldType.FLOAT)) { String propertyValue = property.getValue(); record.setAttribute(attributeName, propertyValue == null ? null : Double.parseDouble(String.valueOf(propertyValue))); } else { String propertyValue; if (property.getName().equals(dataSource.getPrimaryKeyFieldName())) { record.setAttribute(dataSource.getPrimaryKeyFieldName(), id); } else { propertyValue = property.getValue(); record.setAttribute(attributeName, propertyValue); } } } if (property.getDisplayValue() != null) { record.setAttribute("__display_" + attributeName, property.getDisplayValue()); } //if (property.getIsDirty()) { //record.setAttribute("_hilite", "listGridDirtyPropertyHilite"); //record.setAttribute("__dirty_"+attributeName, true); //} } if (entity.isDirty()) { record.setAttribute("_hilite", "listGridDirtyPropertyHilite"); record.setAttribute("__dirty", true); } String[] entityType = entity.getType(); record.setAttribute("_type", entityType); if (!entity.isDirty()) { if (entity.getInactive()) { record.setAttribute("_hilite", "listGridInActivePropertyHilite"); } if (entity.getDeleted()) { record.setAttribute("_hilite", "listGridDeletedPropertyHilite"); } } if (entity.getLocked()) { record.setAttribute("_hilite", "listGridLockedPropertyHilite"); record.setAttribute("__locked", true); record.setAttribute("__lockedUserName", entity.getLockedBy() == null ? "" : entity.getLockedBy()); record.setAttribute("__lockedDate", entity.getLockedDate() == null ? "" : entity.getLockedDate()); } return record; } @Override public TreeNode[] buildRecords(DynamicResultSet result, String[] filterOutIds) { List<TreeNode> recordList = new ArrayList<TreeNode>(); int decrement = 0; for (Entity entity : result.getRecords()) { if (filterOutIds == null || (Arrays.binarySearch(filterOutIds, entity.findProperty(dataSource.getPrimaryKeyFieldName()).getValue()) < 0)) { TreeNode record = (TreeNode) buildRecord(entity, false); recordList.add(record); } else { decrement++; } } result.setTotalRecords(result.getTotalRecords() - decrement); TreeNode[] response = new TreeNode[recordList.size()]; response = recordList.toArray(response); return response; } @Override public Entity buildEntity(Record record, DSRequest request) { Entity entity = new Entity(); //Map<String, Object> dirtyValues = request.getAttributeAsMap("dirtyValues"); List<Property> properties = new ArrayList<Property>(); String[] attributes = record.getAttributes(); for (String attribute : attributes) { if (!attribute.equals("_type") && !attribute.startsWith("__") && dataSource.getField(attribute) != null) { Property property = new Property(); if (record.getAttribute(attribute) != null && dataSource.getField(attribute) != null && dataSource.getField(attribute).getType().equals(FieldType.DATETIME)) { property.setValue(formatter.format(record.getAttributeAsDate(attribute))); } else if (linkedValue != null && dataSource.getField(attribute).getAttribute("fieldType") != null && SupportedFieldType.valueOf(dataSource.getField(attribute).getAttribute("fieldType")) .equals(SupportedFieldType.FOREIGN_KEY)) { property.setValue(dataSource.stripDuplicateAllowSpecialCharacters(linkedValue)); property.setIsDirty(true); } else { property.setValue( dataSource.stripDuplicateAllowSpecialCharacters(record.getAttribute(attribute))); } property.setName(dataSource.getField(attribute).getAttribute("rawName")); //if (dirtyValues != null && dirtyValues.containsKey(property.getName())) { //property.setIsDirty(true); //} properties.add(property); } else if (attribute.equals("_type")) { entity.setType(record.getAttributeAsStringArray("_type")); } } Property fullyQualifiedName = new Property(); fullyQualifiedName.setName("ceilingEntityFullyQualifiedClassname"); fullyQualifiedName.setValue(ceilingEntityFullyQualifiedClassname); fullyQualifiedName.setIsDirty(true); properties.add(fullyQualifiedName); Property[] props = new Property[properties.size()]; props = properties.toArray(props); entity.setProperties(props); return entity; } @Override public void buildFields(final String[] customCriteria, final Boolean overrideFieldSort, final AsyncCallback<DataSource> cb) { BatchManager batchManager = BatchManager.getInstance(); BatchPackage batchPackage = new BatchPackage(); batchPackage.setDataSourceUrl(dataSource.getDataURL()); batchPackage.setPersistencePackage(new PersistencePackage(ceilingEntityFullyQualifiedClassname, null, persistencePerspective, customCriteria, BLCMain.csrfToken)); batchPackage.setAsyncCallback(new AbstractCallback<DynamicResultSet>() { @Override protected void onOtherException(Throwable exception) { super.onOtherException(exception); if (cb != null) { cb.onFailure(exception); } } @Override protected void onSecurityException(ApplicationSecurityException exception) { super.onSecurityException(exception); if (cb != null) { cb.onFailure(exception); } } @Override public void onSuccess(DynamicResultSet result) { super.onSuccess(result); ClassMetadata metadata = result.getClassMetaData(); filterProperties(metadata, new MergedPropertyType[] { MergedPropertyType.PRIMARY, MergedPropertyType.ADORNEDTARGETLIST }, overrideFieldSort, ((AsyncCallbackAdapter) cb).getDataSourceSetupManager()); //Add a hidden field to store the polymorphic type for this entity DataSourceField typeField = new DataSourceTextField("_type"); typeField.setCanEdit(false); typeField.setHidden(true); typeField.setAttribute("permanentlyHidden", true); dataSource.addField(typeField); dataSource.setPolymorphicEntityTree(metadata.getPolymorphicEntities()); dataSource.setDefaultNewEntityFullyQualifiedClassname( dataSource.getPolymorphicEntities().keySet().iterator().next()); if (cb != null) { ((AsyncCallbackAdapter) cb).onBatchSuccess(dataSource); } } }); batchPackage.setBatchOperationType(BatchOperationType.INSPECT); batchManager.addBatchPackage(batchPackage); ((AsyncCallbackAdapter) cb).notifyManager(); } protected void filterProperties(ClassMetadata metadata, final MergedPropertyType[] includeTypes, Boolean overrideFieldSort, final PresenterSequenceSetupManager presenterSequenceSetupManager) throws IllegalStateException { if (BLCMain.isLogDebugEnabled("classmetadata")) { Map<String, List<String>> props = new HashMap<String, List<String>>(); for (Property property : metadata.getProperties()) { String type = property.getMetadata().getInheritedFromType(); List<String> myProps = props.get(type); if (myProps == null) { props.put(type, new ArrayList<String>()); myProps = props.get(type); } myProps.add(property.getName()); } for (String key : props.keySet()) { List<String> myProps = props.get(key); for (String prop : myProps) { BLCMain.logDebug(key + " : " + prop, "classmetadata"); } } } //sort properties based on their display name Property[] properties = metadata.getProperties(); if (overrideFieldSort) { Arrays.sort(properties, new Comparator<Property>() { @Override public int compare(Property o1, Property o2) { if (o1.getMetadata().getFriendlyName() == null && o2.getMetadata().getFriendlyName() == null) { return 0; } else if (o1.getMetadata().getFriendlyName() == null) { return -1; } else if (o2.getMetadata().getFriendlyName() == null) { return 1; } else { return o1.getMetadata().getFriendlyName().compareTo(o2.getMetadata().getFriendlyName()); } } }); } for (final Property property : metadata.getProperties()) { property.getMetadata().accept(new MetadataVisitorAdapter() { @Override public void visit(BasicFieldMetadata metadata) { String mergedPropertyType = metadata.getMergedPropertyType().toString(); if (Arrays.binarySearch(includeTypes, MergedPropertyType.valueOf(mergedPropertyType)) >= 0) { Boolean isDirty = property.getIsDirty(); String rawName = property.getName(); String propertyName = rawName; String fieldType = metadata.getFieldType() == null ? null : metadata.getFieldType().toString(); String secondaryFieldType = metadata.getSecondaryType() == null ? null : metadata.getSecondaryType().toString(); Long length = metadata.getLength() == null ? null : metadata.getLength().longValue(); Boolean required; if (metadata.getRequiredOverride() != null) { required = metadata.getRequiredOverride(); } else { required = metadata.getRequired(); if (required == null) { required = false; } } Boolean mutable = metadata.getMutable(); String inheritedFromType = metadata.getInheritedFromType(); String owningClassFriendlyName = metadata.getOwningClassFriendlyName(); if (owningClassFriendlyName == null) { owningClassFriendlyName = ""; } else { owningClassFriendlyName = getLocalizedString(owningClassFriendlyName); } String[] availableToTypes = metadata.getAvailableToTypes(); String foreignKeyClass = metadata.getForeignKeyClass(); String foreignKeyProperty = metadata.getForeignKeyProperty(); String friendlyName = metadata.getFriendlyName(); if (friendlyName == null || friendlyName.equals("")) { friendlyName = property.getName(); } else { friendlyName = getLocalizedString(friendlyName); } String securityLevel = metadata.getSecurityLevel(); VisibilityEnum visibility = metadata.getVisibility(); if (visibility == null) { visibility = VisibilityEnum.HIDDEN_ALL; } Boolean hidden = visibility == VisibilityEnum.HIDDEN_ALL || visibility == VisibilityEnum.GRID_HIDDEN; FormHiddenEnum formHidden; switch (visibility) { case FORM_HIDDEN: formHidden = FormHiddenEnum.HIDDEN; break; default: formHidden = FormHiddenEnum.NOT_SPECIFIED; break; case GRID_HIDDEN: formHidden = FormHiddenEnum.VISIBLE; break; } String group = metadata.getGroup(); if (group != null && !group.equals("")) { group = getLocalizedString(group); } Integer groupOrder = metadata.getGroupOrder(); Boolean groupCollapsed = metadata.getGroupCollapsed(); String tooltip = metadata.getTooltip(); if (tooltip != null && !tooltip.equals("")) { tooltip = getLocalizedString(tooltip); } String helpText = metadata.getHelpText(); if (helpText != null && !helpText.equals("")) { helpText = getLocalizedString(helpText); } String hint = metadata.getHint(); if (hint != null && !hint.equals("")) { hint = getLocalizedString(hint); } Boolean largeEntry = metadata.isLargeEntry(); Boolean prominent = metadata.isProminent(); Integer order = metadata.getOrder(); String columnWidth = metadata.getColumnWidth(); String[][] enumerationValues = metadata.getEnumerationValues(); String enumerationClass = metadata.getEnumerationClass(); Boolean canEditEnumeration = metadata.getOptionCanEditValues() != null && metadata.getOptionCanEditValues(); if (mutable) { Boolean isReadOnly = metadata.getReadOnly(); if (isReadOnly != null) { mutable = !isReadOnly; } } DataSourceField field; switch (SupportedFieldType.valueOf(fieldType)) { case ID: field = new DataSourceTextField(propertyName, friendlyName); if (!propertyName.contains(".")) { field.setPrimaryKey(true); } field.setCanEdit(false); field.setRequired(required); //field.setValidOperators(getBasicIdOperators()); break; case BOOLEAN: field = new DataSourceBooleanField(propertyName, friendlyName); field.setCanEdit(mutable); //field.setValidOperators(getBasicBooleanOperators()); break; case DATE: field = new DataSourceDateTimeField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); //field.setEditorType(new MiniDateRangeItem()); //field.setValidOperators(getBasicDateOperators()); break; case INTEGER: field = new DataSourceIntegerField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); //field.setValidOperators(getBasicNumericOperators()); break; case DECIMAL: field = new DataSourceFloatField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); //field.setValidOperators(getBasicNumericOperators()); break; case EMAIL: field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); //field.setValidOperators(getBasicTextOperators()); break; case MONEY: field = new DataSourceFloatField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); field.setAttribute("currencyCodeField", metadata.getCurrencyCodeField() == null || metadata.getCurrencyCodeField().equals("") ? null : metadata.getCurrencyCodeField()); //field.setValidOperators(getBasicNumericOperators()); break; case FOREIGN_KEY: { field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); String dataSourceName = null; ForeignKey foreignField = (ForeignKey) persistencePerspective .getPersistencePerspectiveItems() .get(PersistencePerspectiveItemType.FOREIGNKEY); if (foreignField != null && foreignField.getForeignKeyClass().equals(foreignKeyClass)) { dataSourceName = foreignField.getDataSourceName(); } if (dataSourceName == null) { field.setForeignKey(foreignKeyProperty); } else { field.setForeignKey(dataSourceName + "." + foreignKeyProperty); } if (hidden == null) { hidden = true; } field.setRequired(required); //field.setValidOperators(getBasicNumericOperators()); break; } case ADDITIONAL_FOREIGN_KEY: { field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); if (hidden == null) { hidden = true; } field.setRequired(required); if (metadata.getForeignKeyDisplayValueProperty() != null && metadata.getToOneLookupCreatedViaAnnotation() != null && metadata.getToOneLookupCreatedViaAnnotation()) { ForeignKey foreignKey = new ForeignKey(foreignKeyProperty, foreignKeyClass); foreignKey.setDisplayValueProperty(metadata.getForeignKeyDisplayValueProperty()); LookupMetadata lookupMetadata = new LookupMetadata(); lookupMetadata.setLookupForeignKey(foreignKey); lookupMetadata.setParentDataSourceName(metadata.getLookupParentDataSourceName()); lookupMetadata .setTargetDynamicFormDisplayId(metadata.getTargetDynamicFormDisplayId()); lookupMetadata.setFriendlyName(friendlyName); lookupMetadata.setFieldType(SupportedFieldType.ADDITIONAL_FOREIGN_KEY); lookupMetadata.setDefaultDataSource(dataSource); lookupMetadata.setCustomCriteria(metadata.getCustomCriteria()); lookupMetadata.setUseServerSideInspectionCache( metadata.getUseServerSideInspectionCache()); ((DynamicEntityPresenter) presenterSequenceSetupManager.getPresenter()) .initializeLookup(property.getName(), lookupMetadata); } //field.setValidOperators(getBasicNumericOperators()); break; } case BROADLEAF_ENUMERATION: { if (canEditEnumeration) { field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); ComboBoxItem item = new ComboBoxItem(); item.setDefaultToFirstOption(true); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); for (String[] enumerationValue : enumerationValues) { valueMap.put(enumerationValue[0], enumerationValue[1]); } field.setValueMap(valueMap); field.setEditorType(item); } else { field = new DataSourceEnumField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); for (String[] enumerationValue : enumerationValues) { valueMap.put(enumerationValue[0], enumerationValue[1]); } field.setValueMap(valueMap); } //field.setValidOperators(getBasicEnumerationOperators()); break; } case EXPLICIT_ENUMERATION: { if (canEditEnumeration) { field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); ComboBoxItem item = new ComboBoxItem(); item.setDefaultToFirstOption(true); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); for (String[] enumerationValue : enumerationValues) { valueMap.put(enumerationValue[0], enumerationValue[1]); } field.setValueMap(valueMap); field.setEditorType(item); } else { field = new DataSourceEnumField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); for (String[] enumerationValue : enumerationValues) { valueMap.put(enumerationValue[0], enumerationValue[1]); } field.setValueMap(valueMap); } //field.setValidOperators(getBasicEnumerationOperators()); break; } case DATA_DRIVEN_ENUMERATION: { if (canEditEnumeration) { field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); ComboBoxItem item = new ComboBoxItem(); item.setDefaultToFirstOption(true); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); for (String[] enumerationValue : enumerationValues) { valueMap.put(enumerationValue[0], enumerationValue[1]); } field.setValueMap(valueMap); field.setEditorType(item); } else { field = new DataSourceEnumField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); for (String[] enumerationValue : enumerationValues) { valueMap.put(enumerationValue[0], enumerationValue[1]); } field.setValueMap(valueMap); } //field.setValidOperators(getBasicEnumerationOperators()); break; } case PASSWORD: field = new DataSourcePasswordField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); //field.setValidOperators(getBasicTextOperators()); break; case ASSET: field = new DataSourceImageField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); break; default: field = new DataSourceTextField(propertyName, friendlyName); field.setCanEdit(mutable); field.setRequired(required); //field.setValidOperators(getBasicTextOperators()); break; } field.setAttribute("friendlyName", friendlyName); if (metadata.getValidationConfigurations().size() > 0) { field.setValidators(ValidationFactoryManager.getInstance() .createValidators(metadata.getValidationConfigurations(), propertyName)); } if (fieldType.equals(SupportedFieldType.ID.toString())) { field.setHidden(hidden); field.setAttribute("permanentlyHidden", hidden); formHidden = FormHiddenEnum.VISIBLE; } else if (hidden != null) { field.setHidden(hidden); field.setAttribute("permanentlyHidden", hidden); } else if (field.getAttribute("permanentlyHidden") == null) { field.setHidden(false); field.setAttribute("permanentlyHidden", false); } if (securityLevel != null && !"".equals(securityLevel)) { String uniqueID = ceilingEntityFullyQualifiedClassname + field.getName(); org.broadleafcommerce.openadmin.client.security.SecurityManager.getInstance() .registerField(uniqueID, securityLevel); field.setAttribute("uniqueID", uniqueID); field.setAttribute("securityLevel", securityLevel); } field.setAttribute("formHidden", formHidden); if (group != null) { field.setAttribute("formGroup", group); } if (groupOrder != null) { field.setAttribute("formGroupOrder", groupOrder); } if (groupCollapsed != null) { field.setAttribute("formGroupCollapsed", groupCollapsed); } if (tooltip != null) { field.setPrompt(tooltip); } if (helpText != null) { field.setAttribute("helpText", helpText); } if (hint != null) { field.setAttribute("hint", hint); } if (largeEntry != null) { field.setAttribute("largeEntry", largeEntry); } if (prominent != null) { field.setAttribute("prominent", prominent); } if (order != null) { field.setAttribute("presentationLayerOrder", order); } if (length != null) { field.setLength(length.intValue()); } if (columnWidth != null) { field.setAttribute("columnWidth", columnWidth); } if (enumerationValues != null) { field.setAttribute("enumerationValues", enumerationValues); } if (enumerationClass != null) { field.setAttribute("enumerationClass", enumerationClass); } field.setAttribute("canEditEnumeration", canEditEnumeration); if (isDirty != null) { field.setAttribute("isEdited", isDirty); } else { field.setAttribute("isEdited", false); } field.setAttribute("inheritedFromType", inheritedFromType); field.setAttribute("availableToTypes", availableToTypes); field.setAttribute("fieldType", fieldType); field.setAttribute("secondaryFieldType", secondaryFieldType); field.setAttribute("mergedPropertyType", mergedPropertyType); field.setAttribute("rawName", rawName); field.setAttribute("owningClassFriendlyName", owningClassFriendlyName); dataSource.addField(field); } } @Override public void visit(final BasicCollectionMetadata metadata) { //protect against non dynamic entity presenter usage if (presenterSequenceSetupManager != null) { DynamicEntityPresenter.collectionMetadatas .put(presenterSequenceSetupManager.getPresenter().getClass().getName() + "_" + property.getName(), metadata); } } @Override public void visit(AdornedTargetCollectionMetadata metadata) { //protect against non dynamic entity presenter usage if (presenterSequenceSetupManager != null) { DynamicEntityPresenter.collectionMetadatas .put(presenterSequenceSetupManager.getPresenter().getClass().getName() + "_" + property.getName(), metadata); } } @Override public void visit(MapMetadata metadata) { //protect against non dynamic entity presenter usage if (presenterSequenceSetupManager != null) { DynamicEntityPresenter.collectionMetadatas .put(presenterSequenceSetupManager.getPresenter().getClass().getName() + "_" + property.getName(), metadata); } } }); } dataSource.setAttribute("blcCurrencyCode", metadata.getCurrencyCode(), true); } /** * Looks up the given value as a key via the MessageManager. If it's not * found, return the original value passed in * * @return the message for the key specified by <b>value</b> if it exists * or <b>value</b> if it does not */ public String getLocalizedString(String value) { //check if the value name is an i18N key String result = BLCMain.getMessageManager().getString(value); if (result == null) { result = value; } return result; } @Override public void setDataSource(AbstractDynamicDataSource dataSource) { this.dataSource = dataSource; } @Override public String getCeilingEntityFullyQualifiedClassname() { return ceilingEntityFullyQualifiedClassname; } }