/*
* 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 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.ModelDefinition;
import com.adaptrex.core.ext.data.Store;
import com.adaptrex.core.ext.data.StoreDefinition;
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 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;
}
}
/*
* Create the store
*/
Store store = new Store(className, ns);
/*
* Set the model name
*/
if (name != null) store.modelName(name);
/*
* If our store doesn't have a class drop out
*/
Class<?> clazz = store.getConfig().getClazz();
if (clazz == null) {
write ("<!-- Error creating store: Could not find entity for " + className + " -->\n");
return;
}
/*
* Various store options
*/
if (pageSize != null) store.pageSize(Integer.valueOf(pageSize));
if (include != null) store.include(include);
if (exclude != null) store.exclude(exclude);
if (clearOnPageLoad != null && clearOnPageLoad.equals("true")) store.clearOnPageLoad();
if (clearRemovedOnLoad != null && clearRemovedOnLoad.equals("true")) store.clearRemovedOnLoad();
if (autoSync != null && autoSync.equals("true")) store.autoSync();
if (autoLoad != null && autoLoad.equals("true")) store.autoLoad();
if (buffered != null && !buffered.equals("false")) store.buffered();
if (remoteGroup != null && remoteGroup.equals("true")) store.remoteGroup();
if (remoteSort != null && remoteSort.equals("true")) store.remoteSort();
if (remoteFilter != null && remoteFilter.equals("true")) store.remoteFilter(true);
if (sortOnFilter != null && sortOnFilter.equals("true")) store.sortOnFilter(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;
store.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;
store.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;
store.sort(property, direction, root);
}
}
/*
* Buffering
*/
if (buffered != null) {
store.buffered();
if (!buffered.equals("true")) {
String[] parts = buffered.split(":");
store.trailingBufferZone(Integer.valueOf(parts[0]));
if (parts.length > 1) store.leadingBufferZone(Integer.valueOf(parts[1]));
if (parts.length > 1) store.purgePageCount(Integer.valueOf(parts[2]));
}
}
/*
* Add associations
*/
if (associations != null) store.associations(associations);
/*
* Load inline data?
*/
if (inline != null && inline.equals("true")) {
store.inline();
if (where != null) store.where(where);
if (param != null) {
for (String p : param.split(",")) {
String[] parts = p.split(":");
store.param(parts[0],parts[1]);
}
}
if (start != null) store.start(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/";
store.proxy(restPath + (rest.equals("true") ? clazz.getSimpleName().toLowerCase() : rest));
}
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 storeModelName = store.getConfig().getModelName();
String storeName = ns + ".store." + StringUtilities.pluralize(storeModelName);
String modelName = ns + ".model." + storeModelName;
String output =
"Ext.syncRequire('Ext.data.Model');\n" +
"Ext.define(\"" + modelName + "\"," + StringUtilities.json(baseModelDefinition) + ");\n" +
"Ext.define(\"" + storeName + "\"," + StringUtilities.json(storeDefinition) + ");\n";
for (Association assoc : getAllAssociations(baseModelDefinition)) {
ModelDefinition associatedModel = assoc.getAssociatedModelDefinition();
if (associatedModel == null) continue;
output += "Ext.define(\"" + assoc.getModelName() + "\"," + StringUtilities.json(associatedModel) + ");\n";
}
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);
}
}