/*
* Copyright 2012 Adaptrex, LLC
*
* 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 com.adaptrex.core.ext.jsf;
import com.adaptrex.core.Adaptrex;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.faces.component.FacesComponent;
import javax.faces.context.FacesContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adaptrex.core.ext.data.Association;
import com.adaptrex.core.ext.data.DataConfig;
import com.adaptrex.core.ext.data.ModelDefinition;
import com.adaptrex.core.ext.data.RestProxy;
import com.adaptrex.core.ext.data.Store;
import com.adaptrex.core.ext.data.StoreDefinition;
import com.adaptrex.core.persistence.AdaptrexPersistence;
import com.adaptrex.core.persistence.AdaptrexSession;
import com.adaptrex.core.utilities.StringUtilities;
@FacesComponent("ext.data.Store")
public class StoreComponent extends ExtComponentBase {
private Logger log = LoggerFactory.getLogger(StoreComponent.class);
@Override
public String getFamily() {
return "ext.data.store";
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
try {
Map<String, Object> a = getAttributes();
/*
* Definition parameters
*/
String ns = param(a, "ns");
String factoryName = param(a, "factory");
String className = param(a, "table");
String name = param(a, "name");
String rest = param(a, "rest");
String clearOnPageLoad = param(a, "clearonpageload");
String clearRemovedOnLoad = param(a, "clearremovedonload");
String autoSync = param(a, "autosync");
String autoLoad = param(a, "autoload");
String remoteGroup = param(a, "remotegroup");
String remoteSort = param(a, "remotesort");
String remoteFilter = param(a, "remotefilter");
String sortOnFilter = param(a, "sortonfilter");
String buffered = param(a, "buffered");
/*
* Inline Data Parameters
*/
String inline = param(a, "inline");
String start = param(a, "start");
String where = param(a, "where");
String param = param(a, "param");
String filter = param(a, "filter");
/*
* Parameters for both definition and inline data
*/
String include = param(a, "include");
String exclude = param(a, "exclude");
String group = param(a, "group");
String sort = param(a, "sort");
String pageSize = param(a, "pagesize");
String associations = param(a, "associations");
/*
* Get or set the namespace for this store
*/
if (ns != null) {
write("Ext.ns(\"" + ns + "\")");
} else {
ns = (String) getAttribute("ns");
if (ns == null) {
log.warn("Error creating store: Namespace has not been set");
write("<!-- Error creating store: Namespace has not been set -->\n");
return;
}
}
/*
* Get the config
*/
AdaptrexPersistence persistence =
Adaptrex.getAdaptrex().getPersistenceManager().getPersistence(factoryName);
Class<?> clazz = persistence.getEntityClass(className);
DataConfig config = new DataConfig(clazz, persistence);
/*
* Create the store
*/
AdaptrexSession session = new AdaptrexSession(persistence);
Store store = new Store(session, config);
/*
* Set the model name
*/
String modelName = ns + ".model." + (name != null ? name : className);
config.setModelName(modelName);
/*
* If our store doesn't have a class drop out
*/
if (clazz == null) {
write("<!-- Error creating store: Could not find entity for " + className + " -->\n");
return;
}
/*
* Various store options
*/
if (pageSize != null) {
config.setPageSize(Integer.valueOf(pageSize));
}
if (include != null) {
config.include(include);
}
if (exclude != null) {
config.exclude(exclude);
}
if (clearOnPageLoad != null && clearOnPageLoad.equals("true")) {
config.setClearOnPageLoad(true);
}
if (clearRemovedOnLoad != null && clearRemovedOnLoad.equals("true")) {
config.setClearRemovedOnLoad(true);
}
if (autoSync != null && autoSync.equals("true")) {
config.setAutoSync(true);
}
if (autoLoad != null && autoLoad.equals("true")) {
config.setAutoLoad(true);
}
if (remoteGroup != null && remoteGroup.equals("true")) {
config.setRemoteGroup(true);
}
if (remoteSort != null && remoteSort.equals("true")) {
config.setRemoteSort(true);
}
if (remoteFilter != null && remoteFilter.equals("true")) {
config.setRemoteFilter(true);
}
if (sortOnFilter != null && sortOnFilter.equals("true")) {
config.setSortOnFilter(true);
}
/*
* Filtering
*/
if (filter != null) {
for (String filterItem : filter.split(",")) {
String[] parts = filterItem.split("=");
String property = parts[0];
String value = parts.length > 1 ? parts[1] : null;
config.filter(property, value);
}
}
/*
* Grouping
*/
if (group != null) {
for (String groupItem : group.split(",")) {
String[] parts = groupItem.split(":");
String property = parts[0];
String direction = parts.length > 1 ? parts[1] : null;
String root = parts.length > 2 ? parts[2] : null;
config.group(property, direction, root);
}
}
/*
* Sorting
*/
if (sort != null) {
for (String sortItem : sort.split(",")) {
String[] parts = sortItem.split(":");
String property = parts[0];
String direction = parts.length > 1 ? parts[1] : "ASC";
String root = parts.length > 2 ? parts[2] : null;
config.sort(property, direction, root);
}
}
/*
* Buffering
*/
if (buffered != null && buffered.contains("false")) {
config.setBuffered(true);
if (!buffered.equals("true")) {
String[] parts = buffered.split(":");
config.setTrailingBufferZone(Integer.valueOf(parts[0]));
if (parts.length > 1) {
config.setLeadingBufferZone(Integer.valueOf(parts[1]));
}
if (parts.length > 1) {
config.setPurgePageCount(Integer.valueOf(parts[2]));
}
}
}
/*
* Add associations
*/
if (associations != null) {
config.associations(associations);
}
/*
* Load inline data?
*/
if (inline != null && inline.equals("true")) {
config.setInline(true);
}
if (where != null) {
config.setWhere(where);
}
if (param != null) {
for (String p : param.split(",")) {
String[] parts = p.split(":");
config.param(parts[0], parts[1]);
}
}
if (start != null) {
config.setStart(Integer.valueOf(start));
}
/*
* The proxy needs additinoal information from the store. We shouldn't create
* the proxy until the store has been fully configured
*/
if (rest != null) {
String restPath = getRequest().getContextPath() + "/rest/"
+ (rest.equals("true") ? clazz.getSimpleName().toLowerCase() : rest);
config.setProxy(new RestProxy(restPath, config));
}
StoreDefinition storeDefinition = store.getStoreDefinition();
ModelDefinition baseModelDefinition = store.getModelDefinition();
/*
* Write the javascript for this store/model.
*
* During development using Ext.Loader, we need to syncRequire Ext.data.Model.
* If we asynchronously load all of our model's dependencies, they will not be
* available at the time we define our store. If they are not available, our
* model definition will not yet be instantiated and Ext.Loader will attempt (and fail)
* to load it dynamically.
*/
String storeName = ns + ".store." + StringUtilities.pluralize(config.getSimpleModelName());
String output = ""
+ "Ext.syncRequire(['Ext.data.Model','Ext.data.Store','Ext.data.reader.Json','Ext.data.writer.Json'], function(){;\n"
+ "Ext.define(\"" + modelName + "\"," + StringUtilities.json(baseModelDefinition) + ");\n"
+ "Ext.define(\"" + storeName + "\"," + StringUtilities.json(storeDefinition) + ");\n"
+ "Ext.onReady(function() {Ext.create(\"" + storeName + "\", {storeId:\"" + storeName.split(".store.")[1] + "\"})})\n";
for (Association assoc : getAllAssociations(baseModelDefinition)) {
ModelDefinition associatedModel = assoc.getAssociatedModelDefinition();
if (associatedModel == null) {
continue;
}
output += "Ext.define(\"" + assoc.getModelName() + "\"," + StringUtilities.json(associatedModel) + ");\n";
}
output += "});";
writeScript(output);
} catch (Exception e) {
log.warn("Error", e);
}
}
/*
* Each of our associations need to have a model automatically generated
*/
private List<Association> getAllAssociations(ModelDefinition baseModelDefinition) {
List<Association> allAssociations = new ArrayList<Association>();
for (Association assoc : baseModelDefinition.getAssociations()) {
allAssociations.add(assoc);
List<Association> thisAssociations = assoc.getAssociatedModelDefinition().getAssociations();
if (thisAssociations.size() > 0) {
allAssociations.addAll(thisAssociations);
}
}
return allAssociations;
}
private String param(Map<String, Object> a, String p) {
return (String) a.get(p);
}
}