How to abandon rollout with Rollout Config Action Class on a specific target page in MSM in AEM 6.4 - aem

I want to control rollout on a target on the basis of some condition matched in a page. If condition fails, the rollout should not happen.
I have create a rollout config class using BaseActionFactory and BaseAction. Can we abandon rollout on specific target if the condition fails.
#Component(metatype=false)
#Service
public class FilterRoleActionFactory extends BaseActionFactory<BaseAction>{
private static final Logger LOG = LoggerFactory.getLogger(FilterRoleActionFactory.class);
#Property(name="liveActionName", propertyPrivate=true)
private static final String[] LIVE_ACTION_NAME = {FilterRoleAction.class.getSimpleName(), "filterRoleAction"};
#Reference
private RolloutManager rolloutManager;
protected void bindRolloutManager(RolloutManager rolloutManager) {
this.rolloutManager = rolloutManager;
}
protected void unbindRolloutManager(RolloutManager rolloutManager) {
if(this.rolloutManager == rolloutManager) {
this.rolloutManager = null;
}
}
#Override
public String createsAction() {
return LIVE_ACTION_NAME[0];
}
#Override
protected BaseAction newActionInstance(ValueMap config) throws WCMException {
return new FilterRoleAction(config, this);
}
private static final class FilterRoleAction extends BaseAction{
private static final Logger LOG = LoggerFactory.getLogger(FilterRoleAction.class);
private static Map<String, List<String>> roleMap = new HashMap<>();
static {
roleMap.put("master-ip",Arrays.asList("enterprise:role/investment-professional/non-us-investment-professional","enterprise:role/investment-professional/us-investment-professional"));
roleMap.put("master-insti", Arrays.asList("enterprise:role/institutional/non-us-institutional", "enterprise:role/institutional/us-institutional"));
roleMap.put("master-inv", Arrays.asList("enterprise:role/public/public-non-us", "enterprise:role/public/public-us"));
};
protected FilterRoleAction(ValueMap config, BaseActionFactory<? extends LiveAction> liveActionFactory) {
super(config, liveActionFactory);
}
#Override
protected boolean handles(Resource resource, Resource target, LiveRelationship relation, boolean resetRollout)
throws RepositoryException, WCMException {
return target != null && relation.getStatus().isPage();
}
#Override
protected void doExecute(Resource resource, Resource target, LiveRelationship relation, boolean resetRollout)
throws RepositoryException, WCMException {
ValueMap valueMap = resource.getValueMap();
Object tags = valueMap.get(MFSConstants.CQ_COLON_TAGS);
LOG.debug("Tags {} ", tags);
String targetPath = StringUtils.replaceFirst(target.getPath(), "/content/mfs-enterprise/mfscom/masters/", "");
String targetRole = StringUtils.substringBefore(targetPath, "/");
boolean isRolloutAllowed = false;
if(tags != null) {
String[] tagArray = (String[])tags;
for(String tag : tagArray) {
List<String> roles = roleMap.get(targetRole);
if(roles.contains(tag)) {
isRolloutAllowed = true;
break;
}
}
}
if(!isRolloutAllowed) {
LOG.debug("Throwing an Exception, as Role is not allowed. Page Path: {} ",target.getPath());
throw new WCMException("Rollout is not allowed on this page: "+target.getPath()) ;
}
}
}
if isRolloutAllowed is false then i need to abandon the rollout for the target while it should continue processing for other target pages.

Related

How to evaluate consuming time in kafka stream application

I have 1.0.0 kafka stream application with two classes as below 'class FilterByPolicyStreamsApp' and 'class FilterByPolicyTransformerSupplier'. In my application, I read the events, perform some conditional checks and forward to same kafka in another topic. I able to get the producing time with 'eventsForwardTimeInMs' variable in FilterByPolicyTransformerSupplier class. But I unable to get the consuming time (with and without (de)serialization). How will I get this time? Please help me.
FilterByPolicyStreamsApp .java:
public class FilterByPolicyStreamsApp implements CommandLineRunner {
String policyKafkaTopicName="policy";
String policyFilterDataKafkaTopicName = "policy.filter.data";
String bootstrapServers="11.1.1.1:9092";
String sampleEventsKafkaTopicName = 'sample-.*";
String applicationId="filter-by-policy-app";
String policyFilteredEventsKafkaTopicName = "policy.filter.events";
public static void main(String[] args) {
SpringApplication.run(FilterByPolicyStreamsApp.class, args);
}
#Override
public void run(String... arg0) {
String policyGlobalTableName = policyKafkaTopicName + ".table";
String policyFilterDataGlobalTable = policyFilterDataKafkaTopicName + ".table";
Properties config = new Properties();
config.put(StreamsConfig.APPLICATION_ID_CONFIG, applicationId);
config.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
config.put(StreamsConfig.DEFAULT_TIMESTAMP_EXTRACTOR_CLASS_CONFIG, WallclockTimestampExtractor.class);
KStreamBuilder builder = new KStreamBuilder();
builder.globalTable(Serdes.String(), new JsonSerde<>(List.class), policyKafkaTopicName,
policyGlobalTableName);
builder.globalTable(Serdes.String(), new JsonSerde<>(PolicyFilterData.class), policyFilterDataKafkaTopicName,
policyFilterDataGlobalTable);
KStream<String, SampleEvent> events = builder.stream(Serdes.String(),
new JsonSerde<>(SampleEvent.class), Pattern.compile(sampleEventsKafkaTopicName));
events = events.transform(new FilterByPolicyTransformerSupplier(policyGlobalTableName,
policyFilterDataGlobalTable));
events.to(Serdes.String(), new JsonSerde<>(SampleEvent.class), policyFilteredEventsKafkaTopicName);
KafkaStreams streams = new KafkaStreams(builder, config);
streams.start();
streams.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
logger.error(e.getMessage(), e);
}
});
}
}
FilterByPolicyTransformerSupplier.java:
public class FilterByPolicyTransformerSupplier
implements TransformerSupplier<String, SampleEvent, KeyValue<String, SampleEvent>> {
private String policyGlobalTableName;
private String policyFilterDataGlobalTable;
public FilterByPolicyTransformerSupplier(String policyGlobalTableName,
String policyFilterDataGlobalTable) {
this.policyGlobalTableName = policyGlobalTableName;
this.policyFilterDataGlobalTable = policyFilterDataGlobalTable;
}
#Override
public Transformer<String, SampleEvent, KeyValue<String, SampleEvent>> get() {
return new Transformer<String, SampleEvent, KeyValue<String, SampleEvent>>() {
private KeyValueStore<String, List<String>> policyStore;
private KeyValueStore<String, PolicyFilterData> policyMetadataStore;
private ProcessorContext context;
#Override
public void close() {
}
#Override
public void init(ProcessorContext context) {
this.context = context;
// Call punctuate every 1 second
this.context.schedule(1000);
policyStore = (KeyValueStore<String, List<String>>) this.context
.getStateStore(policyGlobalTableName);
policyMetadataStore = (KeyValueStore<String, PolicyFilterData>) this.context
.getStateStore(policyFilterDataGlobalTable);
}
#Override
public KeyValue<String, SampleEvent> punctuate(long arg0) {
return null;
}
#Override
public KeyValue<String, SampleEvent> transform(String key, SampleEvent event) {
long eventsForwardTimeInMs = 0;
long forwardedEventCouunt = 0;
List<String> policyIds = policyStore.get(event.getCustomerCode().toLowerCase());
if (policyIds != null) {
for (String policyId : policyIds) {
/*
PolicyFilterData policyFilterMetadata = policyMetadataStore.get(policyId);
Do some condition checks on the event. If it satisfies then will forward them.
if(policyFilterMetadata == null){
continue;
}
*/
// Using context forward as event can map to multiple policies
long startForwardTime = System.currentTimeMillis();
context.forward(policyId, event);
forwardedEventCouunt++;
eventsForwardTimeInMs += System.currentTimeMillis() - startForwardTime;
}
}
return null;
}
};
}
}

Sling Forward with SyntheticResource

I'm trying to build a Sling servlet that returns a modified value of a resource from the JCR. I dont want to change the original resource, so I create a SyntheticResource and make my manipulations. I then return it back using the RequestDispatcher.
The following code doesn't return the Modified content as expected and I don't see any errors in the log either. Can you tell me what I'm doing wrong here
#SlingServlet(methods = "GET", resourceTypes = "sling/components/test", selectors = "test")
public class TestServlet extends SlingSafeMethodsServlet {
/**
*
*/
private static final long serialVersionUID = 4078524820231933974L;
private final Logger log = LoggerFactory.getLogger(getClass());
#Reference
ResourceResolverFactory resolverFactory;
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
Map<String, Object> param = new HashMap<String, Object>();
ResourceResolver resolver = null;
response.setContentType("text/html");
StringWriterResponse writerResponse = new StringWriterResponse(response);
PrintWriter writer = response.getWriter();
try {
param.put(ResourceResolverFactory.SUBSERVICE, "testService");
final String path = request.getRequestPathInfo().getResourcePath();
resolver = resolverFactory.getServiceResourceResolver(param);
final Resource resource = resolver.getResource(path);
String resourceType = resource.getResourceType();
Resource testResource = new SyntheticResource(resolver,
path, resourceType) {
public <T> T adaptTo(Class<T> type) {
if (type == ValueMap.class) {
ModifiableValueMap map = resource
.adaptTo(ModifiableValueMap.class);
map.put("jcr:title", "Modified Title");
return (T)map;
}
return super.adaptTo(type);
}
};
RequestDispatcherOptions requestDispatcherOptions = new RequestDispatcherOptions();
requestDispatcherOptions.setReplaceSelectors("");
final RequestDispatcher requestDispatcher = request.getRequestDispatcher(testResource, requestDispatcherOptions);
requestDispatcher.forward(request, writerResponse);
// log.debug( writerResponse.getString() );
writer.println(writerResponse.getString());
response.setStatus(HttpServletResponse.SC_OK );
} catch (Exception e) {
log.error("Exception: ", e);
} finally {
if( resolver != null) {
resolver.close();
}
if( writer != null ){
writer.close();
}
if (writerResponse != null) {
writerResponse.clearWriter();
}
}
}
}
Using a ResourceDecorator would be simpler, it can return a ResourceWrapper that implements the required changes. Just be careful to keep the decorator's decorate method efficient when it's called for a Resource that it doesn't want to decorate, as it will be called for all Resources.

spring data mongodb converter

I am using spring data mongo-db 1.4.1.RELEASE.
My entity 'Event' has a getter method which is calculated based on other properties:
public int getStatus() {
return (getMainEventId() == null) ? (elapseTimeInMin() < MINIMUM_TIME ? CANDIDATE :
VALID) : POINTER;
}
I wanted the property 'status' to be persisted only through the getter ,so I wrote converters:
#WritingConverter
public class EventWriteConverter implements Converter<Event ,BasicDBObject > {
static final Logger logger = LoggerFactory.getLogger(EventWriteConverter.class.getCanonicalName());
public BasicDBObject convert(Event event) {
logger.info("converting " +event );
if (event.getMainEventId() != null)
return new BasicDBObject("mainEventId", event.getMainEventId() );
BasicDBObject doc = new BasicDBObject("status",event.getStatus()).
append("updated_date",new Date()).
append("start",event.getS0()).
append("end",event.getS1()).
append("location",event.getLocation()).
;
BasicDBList list = new BasicDBList();
doc.append("access_points",event.getHotPoints());
return doc;
}
#ReadingConverter
public class EventReadConverter implements Converter<BasicDBObject, Event> {
#Inject
HotPointRepositry hotRepositry;
static final Logger logger = LoggerFactory.getLogger(EventReadConverter.class.getCanonicalName());
public Event convert(BasicDBObject doc) {
logger.info(" converting ");
Event event = new Event();
event.setId(doc.getObjectId("_id"));
event.setS0(doc.getDate("start"));
event.setS1(doc.getDate("end"));
BasicDBList dblist = (BasicDBList) doc.get("hot_points");
if (dblist != null) {
for (Object obj : dblist) {
ObjectId hotspotId = ((BasicDBObject) obj).getObjectId("_id");
event.addHot(hotRepositry.findOne(hotId));
}
}
dblist = (BasicDBList) doc.get("devices");
if (dblist != null) {
for (Object obj : dblist)
event.addDevice(obj.toString());
}
event.setMainEventId(doc.getObjectId("mainEventId"));
return event;
}
}
My test mongo configuration is
#Profile("test")
#Configuration
#EnableMongoRepositories(basePackages = "com.echo.spring.data.mongo")
#ComponentScan(basePackages = "com.echo.spring.data.mongo" )
public class MongoDbTestConfig extends AbstractMongoConfiguration {
static final Logger logger = LoggerFactory.getLogger(MongoDbTestConfig.class.getCanonicalName());
#Override
protected String getDatabaseName() {
return "echo";
}
#Override
public Mongo mongo() {
return new Fongo("echo-test").getMongo();
}
#Override
protected String getMappingBasePackage() {
return "com.echo.spring.data.mongo";
}
#Bean
#Override
public CustomConversions customConversions() {
logger.info("loading custom converters");
List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>();
converterList.add(new EventReadConverter());
converterList.add(new EventWriteConverter());
CustomConversions cus = new CustomConversions(converterList);
return new CustomConversions(converterList);
}
}
And my test (using fongo) is
ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = MongoDbTestConfig.class )
public class SampleMongoApplicationTests {
#Test
#ShouldMatchDataSet(location = "/MongoJsonData/events.json")
public void shouldSaveEvent() throws IOException {
URL url = Resources.getResource("MongoJsonData/events.json");
List<String> lines = Resources.readLines(url,Charsets.UTF_8);
for (String line : lines) {
Event event = objectMapper.readValue(line.getBytes(),Event.class);
eventRepository.save(event);
}
}
I can see the converters are loaded when the configuration customConversions() is called
I added logging and breakpoints in the convert methods but they do not seems to be
called when I run or debug, though they are loaded .
What am I doing wrong ?
I had a similar situation, I followed Spring -Mongodb storing/retrieving enums as int not string
and I need both the converter AND converterFactory wired to get it working.

URL issue in Facebook in BlackBerry

I have integrated Facebook in my app and trying to share some content.When I call FaceBookMain() ,it shows error like :
"Success
SECURITY WARNINNG:Please treat the URL above as you would your password and do not share it with anyone."
Sometimes this error comes after login with Facebook in browser(Webview) otherwise it comes just after clicking on share button.
Most important thing here is ,I am not facing this problem in simulator.Sharing with Facebook is working properly in Simulator but not in Device.
I am adding some class files with it:
Here is FacebookMain.java class:
import net.rim.device.api.applicationcontrol.ApplicationPermissions;
import net.rim.device.api.applicationcontrol.ApplicationPermissionsManager;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import net.rim.device.api.ui.UiApplication;
public class FacebookMain implements ActionListener{// extends MainScreen implements ActionListener {
// Constants
public final static String NEXT_URL = "http://www.facebook.com/connect/login_success.html";
public final static String APPLICATION_ID = "406758776102494";//"533918076671162" ;
private final static long persistentObjectId = 0x854d1b7fa43e3577L;
static final String ACTION_ENTER = "updateStatus";
static final String ACTION_SUCCESS = "statusUpdated";
static final String ACTION_ERROR = "error";
private ActionScreen actionScreen;
private PersistentObject store;
private LoginScreen loginScreen;
private LogoutScreen logoutScreen;
private HomeScreen homeScreen;
private UpdateStatusScreen updateStatusScreen;
private RecentUpdatesScreen recentUpdatesScreen;
private UploadPhotoScreen uploadPhotoScreen;
private FriendsListScreen friendsListScreen;
private PokeFriendScreen pokeFriendScreen;
private PostWallScreen postWallScreen;
private SendMessageScreen sendMessageScreen;
private String postMessage;
private FacebookContext fbc;
public static boolean isWallPosted=false;
public static boolean isFacebookScreen = false;
public FacebookMain(String postMessge) {
this.postMessage= postMessge;
isFacebookScreen = true;
checkPermissions();
fbc=new FacebookContext(NEXT_URL, APPLICATION_ID);
loginScreen = new LoginScreen(fbc,"KingdomConnect: "+postMessge);
loginScreen.addActionListener(this);
UiApplication.getUiApplication().pushScreen(loginScreen);
}
private void init() {
store = PersistentStore.getPersistentObject(persistentObjectId);
synchronized (store) {
if (store.getContents() == null) {
store.setContents(new FacebookContext(NEXT_URL, APPLICATION_ID));
store.commit();
}
}
fbc = (FacebookContext) store.getContents();
}
private void checkPermissions() {
ApplicationPermissionsManager apm = ApplicationPermissionsManager.getInstance();
ApplicationPermissions original = apm.getApplicationPermissions();
if ((original.getPermission(ApplicationPermissions.PERMISSION_INPUT_SIMULATION) == ApplicationPermissions.VALUE_ALLOW) && (original.getPermission(ApplicationPermissions.PERMISSION_DEVICE_SETTINGS) == ApplicationPermissions.VALUE_ALLOW) && (original.getPermission(ApplicationPermissions.PERMISSION_CROSS_APPLICATION_COMMUNICATION) == ApplicationPermissions.VALUE_ALLOW) && (original.getPermission(ApplicationPermissions.PERMISSION_INTERNET) == ApplicationPermissions.VALUE_ALLOW) && (original.getPermission(ApplicationPermissions.PERMISSION_SERVER_NETWORK) == ApplicationPermissions.VALUE_ALLOW) && (original.getPermission(ApplicationPermissions.PERMISSION_EMAIL) == ApplicationPermissions.VALUE_ALLOW)) {
return;
}
/*ApplicationPermissions permRequest = new ApplicationPermissions();
permRequest.addPermission(ApplicationPermissions.PERMISSION_INPUT_SIMULATION);
permRequest.addPermission(ApplicationPermissions.PERMISSION_DEVICE_SETTINGS);
permRequest.addPermission(ApplicationPermissions.PERMISSION_CROSS_APPLICATION_COMMUNICATION);
permRequest.addPermission(ApplicationPermissions.PERMISSION_INTERNET);
permRequest.addPermission(ApplicationPermissions.PERMISSION_SERVER_NETWORK);
permRequest.addPermission(ApplicationPermissions.PERMISSION_EMAIL);
permRequest.addPermission(ApplicationPermissions.PERMISSION_INTERNET);
permRequest.addPermission(ApplicationPermissions.PERMISSION_AUTHENTICATOR_API);
permRequest.addPermission(ApplicationPermissions.PERMISSION_SERVER_NETWORK);
permRequest.addPermission(ApplicationPermissions.PERMISSION_WIFI);*/
ApplicationPermissions permRequest = new ApplicationPermissions();
permRequest.addPermission(ApplicationPermissions.PERMISSION_INPUT_SIMULATION);
permRequest.addPermission(ApplicationPermissions.PERMISSION_DEVICE_SETTINGS);
permRequest.addPermission(ApplicationPermissions.PERMISSION_CROSS_APPLICATION_COMMUNICATION);
permRequest.addPermission(ApplicationPermissions.PERMISSION_INTERNET);
permRequest.addPermission(ApplicationPermissions.PERMISSION_SERVER_NETWORK);
permRequest.addPermission(ApplicationPermissions.PERMISSION_EMAIL);
boolean acceptance = ApplicationPermissionsManager.getInstance().invokePermissionsRequest(permRequest);
if (acceptance) {
// User has accepted all of the permissions.
return;
} else {
}
}
public void saveContext(FacebookContext pfbc) {
synchronized (store) {
store.setContents(pfbc);
System.out.println(pfbc);
store.commit();
}
}
public void logoutAndExit() {
saveContext(null);
logoutScreen = new LogoutScreen(fbc);
logoutScreen.addActionListener(this);
}
public void saveAndExit() {
saveContext(fbc);
exit();
}
private void exit() {
AppenderFactory.close();
System.exit(0);
}
public void onAction(Action event) {}
}
It is Facebook.java class:
public class Facebook {
protected Logger log = Logger.getLogger(getClass());
public static String API_URL = "https://graph.facebook.com";
public Facebook() {
}
public static Object read(String path, String accessToken) throws FacebookException {
return read(path, null, accessToken);
}
public static Object read(String path, Parameters params, String accessToken) throws FacebookException {
Hashtable args = new Hashtable();
args.put("access_token", accessToken);
args.put("format", "JSON");
if ((params != null) && (params.getCount() > 0)) {
Enumeration paramNamesEnum = params.getParameterNames();
while (paramNamesEnum.hasMoreElements()) {
String paramName = (String) paramNamesEnum.nextElement();
String paramValue = params.get(paramName).getValue();
args.put(paramName, paramValue);
}
}
try {
StringBuffer responseBuffer = HttpClient.getInstance().doGet(API_URL + '/' + path, args);
if (responseBuffer.length() == 0) {
throw new Exception("Empty response");
}
return new JSONObject(new JSONTokener(responseBuffer.toString()));
} catch (Throwable t) {
t.printStackTrace();
throw new FacebookException(t.getMessage());
}
}
public static Object write(String path, Object object, String accessToken) throws FacebookException {
Hashtable data = new Hashtable();
data.put("access_token", accessToken);
data.put("format", "JSON");
try {
JSONObject jsonObject = (JSONObject) object;
Enumeration keysEnum = jsonObject.keys();
while (keysEnum.hasMoreElements()) {
String key = (String) keysEnum.nextElement();
Object val = jsonObject.get(key);
if (!(val instanceof JSONObject)) {
data.put(key, val.toString());
}
}
StringBuffer responseBuffer = HttpClient.getInstance().doPost(API_URL + '/' + path, data);
if (responseBuffer.length() == 0) {
throw new FacebookException("Empty response");
}
return new JSONObject(new JSONTokener(responseBuffer.toString()));
} catch (Exception e) {
throw new FacebookException(e.getMessage());
}
}
public static Object delete(String path, String accessToken) throws FacebookException {
Hashtable data = new Hashtable();
data.put("access_token", accessToken);
data.put("format", "JSON");
data.put("method", "delete");
try {
StringBuffer responseBuffer = HttpClient.getInstance().doPost(API_URL + '/' + path, data);
if (responseBuffer.length() == 0) {
throw new FacebookException("Empty response");
}
return new JSONObject(new JSONTokener(responseBuffer.toString()));
} catch (Exception e) {
throw new FacebookException(e.getMessage());
}
}
}
And it is BrowserScreen.class:
public class BrowserScreen extends ActionScreen {
// int[] preferredTransportTypes = { TransportInfo.TRANSPORT_TCP_CELLULAR, TransportInfo.TRANSPORT_WAP2, TransportInfo.TRANSPORT_BIS_B };
int[] preferredTransportTypes = TransportInfo.getAvailableTransportTypes();//{ TransportInfo.TRANSPORT_BIS_B };
ConnectionFactory cf;
BrowserFieldConfig bfc;
BrowserField bf;
String url;
public BrowserScreen(String pUrl) {
super();
url = pUrl;
cf = new ConnectionFactory();
cf.setPreferredTransportTypes(preferredTransportTypes);
bfc = new BrowserFieldConfig();
bfc.setProperty(BrowserFieldConfig.ALLOW_CS_XHR, Boolean.TRUE);
bfc.setProperty(BrowserFieldConfig.JAVASCRIPT_ENABLED, Boolean.TRUE);
bfc.setProperty(BrowserFieldConfig.USER_SCALABLE, Boolean.TRUE);
bfc.setProperty(BrowserFieldConfig.MDS_TRANSCODING_ENABLED, Boolean.FALSE);
bfc.setProperty(BrowserFieldConfig.NAVIGATION_MODE, BrowserFieldConfig.NAVIGATION_MODE_POINTER);
bfc.setProperty(BrowserFieldConfig.VIEWPORT_WIDTH, new Integer(Display.getWidth()));
// bfc.setProperty(BrowserFieldConfig.CONNECTION_FACTORY, cf);
bf = new BrowserField(bfc);
}
public void browse() {
show();
fetch();
}
public void show() {
add(bf);
}
public void fetch() {
bf.requestContent(url);
}
public void hide() {
delete(bf);
}
}
If any body has any clue or want some more related code to get it,please let me know.
do not use secure connection. use http instead of https.
you can refer here
same problem is presented in stackoverflow
facebook warning

How to re-render a specific node in gwt cell tree

I am implementing a directory structure like Windows Explorer. I want to re-render a specific node of tree after any folder operations is done such as add folder, remove folder... etc
private ListDataProvider<Object> dataProvider= new ListDataProvider<Object>();
private Object current;//store object of currentNode;
private Map<Object, ListDataProvider<Object>> keyprovider =
new HashMap<Object,ListDataProvider<Object>>();
private CellTree tree;
// keeps a map for storing dataproviders in each hierarchy ,
public void setListToCurrentNode(List<Object> newList){
//adding this newlist to current data provider not reflecting to display
keyprovider.get(currentObject).setList(newList);
}
public void onModuleLoad(){
treeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
//setting current object as selected node
current = treeSelectionModel.getSelectedObject();
}
});
}
Data providers force to re-render corresponding DOM. Code below demonstrates how it works.
This example generates 2-leveled tree, where you can refresh (re-generate) leaf nodes by pressing Enter key on selected root node.
I tried to keep code as simple as possible, all needed stuff contained right here.
public class TestEntryPoint implements EntryPoint {
private static final Logger LOG = Logger.getLogger(TestEntryPoint.class.getName());
class Item {
String name;
boolean leaf;
public Item(String name, boolean leaf) {
this.name = name;
this.leaf = leaf;
}
#Override
public String toString() {
return "Item {name=" + name + ", leaf=" + leaf + "}";
}
}
class ItemCell extends AbstractCell<Item> {
public ItemCell() {
super("keydown");
}
#Override
public void render(Context context, Item value, SafeHtmlBuilder sb) {
if (value != null) sb.appendEscaped(value.name);
}
#Override
protected void onEnterKeyDown(
Context context, Element parent, Item value, NativeEvent event, ValueUpdater<Item> valueUpdater) {
LOG.info("ItemCell.onEnterKeyDown: value=" + value);
if (value == null || value.leaf) return;
ListDataProvider<Item> leafDataProvider = leafDataProviders.get(value.name);
if (leafDataProvider == null) return;
// -->> Here we generate new childs of selected root node
leafDataProvider.setList(generateLeafs());
}
}
class ItemTreeViewModel implements TreeViewModel {
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
return new DefaultNodeInfo<Item>(
value == null ? rootDataProvider : leafDataProviders.get(((Item) value).name),
new ItemCell());
}
#Override
public boolean isLeaf(Object value) {
return (value instanceof Item) && ((Item) value).leaf;
}
}
private int id = 0;
private CellTree cellTree;
private ListDataProvider<Item> rootDataProvider;
private Map<String, ListDataProvider<Item>> leafDataProviders = new HashMap<String, ListDataProvider<Item>>();
private List<Item> generateLeafs() {
List<Item> leafList = new ArrayList<Item>(5);
for (int j = 0; j < 5; ++j)
leafList.add(new Item("Leaf Item " + (++id), true));
return leafList;
}
public void onModuleLoad() {
List<Item> rootList = new ArrayList<Item>(10);
for (int i = 0; i < 10; ++i) {
Item rootItem = new Item("Root Item " + (++id), false);
rootList.add(rootItem);
leafDataProviders.put(rootItem.name, new ListDataProvider<Item>(generateLeafs()));
}
rootDataProvider = new ListDataProvider<Item>(rootList);
cellTree = new CellTree(new ItemTreeViewModel(), null);
cellTree.setAnimationEnabled(true);
RootLayoutPanel.get().add(cellTree);
}
}
Solved by Changing Listdataprovider into AsyncDataProvider ,Implementation is below
private final class DataProvider extends AsyncDataProvider<Object> {
private Object value;
private List Objs;
DataProvider(Object value) {
this.value = value;
}
public void update(List objs) {//Call update when you wanted to refresh tree
this.objs=objs;
for (HasData<Object> disp : getDataDisplays()) {
this.onRangeChanged(disp);
break;
}
}
#Override
protected void onRangeChanged(final HasData<Object> display) {
updateRowData(0, objs);
updateRowCount(objs.size(), true);
}