@Test public void testCoalesceNotificationsSet() { InvalidateCacheNotificationCoalescer coalescer = new InvalidateCacheNotificationCoalescer(); ICacheEntryFilter<Object, Object> filter1 = new KeyCacheEntryFilter<Object, Object>( CollectionUtility.<Object>arrayList(CodeType1.class)); ICacheEntryFilter<Object, Object> filter2 = new KeyCacheEntryFilter<Object, Object>( CollectionUtility.<Object>arrayList(CodeType2.class)); List<InvalidateCacheNotification> testList = CollectionUtility.arrayList( new InvalidateCacheNotification(CACHE_ID_1, filter1), new InvalidateCacheNotification(CACHE_ID_1, filter2), new InvalidateCacheNotification(CACHE_ID_2, filter2), new InvalidateCacheNotification(CACHE_ID_3, new AllCacheEntryFilter<>()), new InvalidateCacheNotification(CACHE_ID_3, filter2)); List<InvalidateCacheNotification> res = coalescer.coalesce(testList); assertEquals(3, res.size()); for (InvalidateCacheNotification notification : res) { if (CACHE_ID_1.equals(notification.getCacheId())) { Set<?> keys = ((KeyCacheEntryFilter<?, ?>) notification.getFilter()).getKeys(); assertEquals(2, keys.size()); assertTrue(keys.contains(CodeType1.class)); assertTrue(keys.contains(CodeType2.class)); } else if (CACHE_ID_2.equals(notification.getCacheId())) { Set<?> keys = ((KeyCacheEntryFilter<?, ?>) notification.getFilter()).getKeys(); assertEquals(1, keys.size()); assertTrue(keys.contains(CodeType2.class)); } else if (CACHE_ID_3.equals(notification.getCacheId())) { assertTrue(notification.getFilter() instanceof AllCacheEntryFilter); } else { fail("invalid cacheId" + notification.getCacheId()); } } }
protected boolean checkValueEqualToDefaultValue(Object value, Object defaultValue) { // Now compare the given value to the found default value if (value == null && defaultValue == null) { return true; } if (value == null || defaultValue == null) { return false; } if (defaultValue instanceof JSONObject) { if (value instanceof JSONObject) { JSONObject jsonValue = (JSONObject) value; JSONObject jsonDefaultValue = (JSONObject) defaultValue; // Special case: The property cannot be removed, but maybe we can remove some of the // objects attributes return filterDefaultObject(jsonValue, jsonDefaultValue); } if (value instanceof JSONArray) { JSONArray jsonValue = (JSONArray) value; JSONObject jsonDefaultValue = (JSONObject) defaultValue; // Special case: Apply default value object to each element in the array filterDefaultObject(jsonValue, jsonDefaultValue); } return false; } // Convert JSONArrays to collections to be able to compare them if (value instanceof JSONArray) { value = jsonArrayToCollection((JSONArray) value, true); } if (defaultValue instanceof JSONArray) { defaultValue = jsonArrayToCollection((JSONArray) defaultValue, false); } if (value instanceof List<?> && defaultValue instanceof List<?>) { return CollectionUtility.equalsCollection( (List<?>) value, (List<?>) defaultValue); // same order } if (value instanceof Collection<?> && defaultValue instanceof Collection<?>) { return CollectionUtility.equalsCollection( (Collection<?>) value, (Collection<?>) defaultValue); // any order } try { // Try to match types (to make Integer "1" equal to Double "1.0") value = TypeCastUtility.castValue(value, defaultValue.getClass()); } catch (RuntimeException e) { // Types do not match return false; } return CompareUtility.equals(value, defaultValue); }
/** * Removes all properties from "valueObject" where the value matches the corresponding value in * "defaultValueObject". * * @return <code>true</code> of the two objects are completely equal and no properties remain in * "valueObject". This means that the valueObject itself MAY be removed. Return value <code> * false</code> means that not all properties are equal (but nevertheless, some properties may * have been removed from valueObject). */ protected boolean filterDefaultObject(JSONObject valueObject, JSONObject defaultValueObject) { boolean sameKeys = CollectionUtility.equalsCollection(valueObject.keySet(), defaultValueObject.keySet()); for (Iterator it = valueObject.keys(); it.hasNext(); ) { String prop = (String) it.next(); Object subValue = valueObject.opt(prop); Object subDefaultValue = defaultValueObject.opt(prop); boolean valueEqualToDefaultValue = checkValueEqualToDefaultValue(subValue, subDefaultValue); if (valueEqualToDefaultValue) { // Property value value is equal to the static default value -> remove the property it.remove(); } else { // Special case: Check if there is a "pseudo" default value, which will not // be removed itself, but might have sub-properties removed. subDefaultValue = defaultValueObject.opt("~" + prop); checkValueEqualToDefaultValue(subValue, subDefaultValue); } } // Even more special case: If valueObject is now empty and it used to have the same keys as // the defaultValueObject, it is considered equal to the default value and MAY be removed. if (valueObject.length() == 0 && sameKeys) { return true; } return false; }
public void dispatchNotifications(List<ClientNotificationMessage> notifications) { IClientSessionRegistry notificationService = BEANS.get(IClientSessionRegistry.class); if (notifications == null) { LOG.error("Notifications null. Please check your configuration"); return; } for (ClientNotificationMessage message : notifications) { ClientNotificationAddress address = message.getAddress(); Serializable notification = message.getNotification(); LOG.debug("Processing client notification {}", notification); if (address.isNotifyAllNodes()) { // notify all nodes LOG.debug("Notify all nodes"); dispatch(notification); } else if (address.isNotifyAllSessions()) { // notify all sessions LOG.debug("Notify all sessions"); for (IClientSession session : notificationService.getAllClientSessions()) { dispatch(session, notification); } } else if (CollectionUtility.hasElements(address.getSessionIds())) { // notify all specified sessions LOG.debug("Notify sessions by session id: {}", address.getSessionIds()); for (String sessionId : address.getSessionIds()) { IClientSession session = notificationService.getClientSession(sessionId); if (session == null) { LOG.warn("received notification for invalid session '{}'.", sessionId); } else { dispatch(session, notification); } } } else if (CollectionUtility.hasElements(address.getUserIds())) { LOG.debug("Notify sessions by user id: {}", address.getUserIds()); for (String userId : address.getUserIds()) { for (IClientSession session : notificationService.getClientSessionsForUser(userId)) { dispatch(session, notification); } } } } }
protected void generateObjectTypeHierarchyRec( JSONObject json, List<String> currentParentObjectTypes, Map<String, List<String>> targetMap) { if (json == null) { return; } if (targetMap == null) { throw new IllegalArgumentException("Argument 'targetMap' must not be null"); } for (Iterator it = json.keys(); it.hasNext(); ) { String objectType = (String) it.next(); Object subHierarchy = json.opt(objectType); // Create a copy of the current object type list and add the current type to the front List<String> newParentObjectTypes = new ArrayList<>(); newParentObjectTypes.add(objectType); if (currentParentObjectTypes != null) { newParentObjectTypes.addAll(currentParentObjectTypes); } if (subHierarchy instanceof JSONObject && ((JSONObject) subHierarchy).length() > 0) { generateObjectTypeHierarchyRec((JSONObject) subHierarchy, newParentObjectTypes, targetMap); } // Store current result List<String> existingParentObjectTypes = targetMap.get(objectType); if (existingParentObjectTypes != null) { throw new IllegalStateException( "Object type '" + objectType + "' has ambiguous parent object types: [" + CollectionUtility.format(existingParentObjectTypes) + "] vs. [" + CollectionUtility.format(newParentObjectTypes) + "]"); } targetMap.put(objectType, newParentObjectTypes); } }
@Test public void testVisit() throws Exception { final BlockingCountDownLatch latch = new BlockingCountDownLatch(3); IFuture<Void> future1 = Jobs.getJobManager() .schedule( new IRunnable() { @Override public void run() throws Exception { latch.countDownAndBlock(); } }, Jobs.newInput() .withRunContext(RunContexts.copyCurrent()) .withExceptionHandling(null, false)); IFuture<Void> future2 = Jobs.getJobManager() .schedule( new IRunnable() { @Override public void run() throws Exception { latch.countDownAndBlock(); } }, Jobs.newInput() .withRunContext(RunContexts.copyCurrent()) .withExceptionHandling(null, false)); IFuture<Void> future3 = Jobs.getJobManager() .schedule( new IRunnable() { @Override public void run() throws Exception { latch.countDownAndBlock(); } }, Jobs.newInput() .withRunContext(RunContexts.copyCurrent()) .withExceptionHandling(null, false)); assertTrue(latch.await()); // RUN THE TEST final Set<IFuture<?>> protocol = new HashSet<>(); Jobs.getJobManager() .visit( Jobs.newFutureFilterBuilder().andMatchFuture(future1, future2, future3).toFilter(), new IVisitor<IFuture<?>>() { @Override public boolean visit(IFuture<?> future) { protocol.add(future); return true; } }); // VERIFY assertEquals(CollectionUtility.hashSet(future1, future2, future3), protocol); }
@Test public void testShutdown() throws Exception { final Set<String> protocol = Collections.synchronizedSet( new HashSet<String>()); // synchronized because modified/read by different threads. final BlockingCountDownLatch setupLatch = new BlockingCountDownLatch(3); final BlockingCountDownLatch verifyLatch = new BlockingCountDownLatch(3); Jobs.getJobManager() .schedule( new IRunnable() { @Override public void run() throws Exception { try { setupLatch.countDownAndBlock(); } catch (InterruptedException e) { protocol.add("interrupted-1"); } finally { verifyLatch.countDown(); } } }, Jobs.newInput() .withRunContext(RunContexts.copyCurrent()) .withExceptionHandling(null, false)); Jobs.getJobManager() .schedule( new IRunnable() { @Override public void run() throws Exception { try { setupLatch.countDownAndBlock(); } catch (InterruptedException e) { protocol.add("interrupted-2"); } finally { verifyLatch.countDown(); } } }, Jobs.newInput() .withRunContext(RunContexts.copyCurrent()) .withExceptionHandling(null, false)); Jobs.getJobManager() .schedule( new IRunnable() { @Override public void run() throws Exception { try { setupLatch.countDownAndBlock(); } catch (InterruptedException e) { protocol.add("interrupted-3"); } finally { verifyLatch.countDown(); } } }, Jobs.newInput() .withRunContext(RunContexts.copyCurrent()) .withExceptionHandling(null, false)); assertTrue(setupLatch.await()); // RUN THE TEST Jobs.getJobManager().shutdown(); // VERIFY assertTrue(verifyLatch.await()); assertEquals( CollectionUtility.hashSet("interrupted-1", "interrupted-2", "interrupted-3"), protocol); try { Jobs.schedule(mock(IRunnable.class), Jobs.newInput()); fail("AssertionError expected"); } catch (AssertionException e) { // NOOP } }
protected Set<String> getExistingTables() { StringArrayHolder tables = new StringArrayHolder(); SQL.selectInto(SQLs.SELECT_TABLE_NAMES, new NVPair("result", tables)); return CollectionUtility.hashSet(tables.getValue()); }
@Override protected List<String> getConfiguredFileExtensions() { return CollectionUtility.arrayList("png", "bmp", "jpg", "jpeg", "gif"); }