List of usage examples for org.apache.commons.lang3 SerializationUtils clone
public static <T extends Serializable> T clone(final T object)
Deep clone an Object using serialization.
This is many times slower than writing clone methods by hand on all objects in your object graph.
From source file:com.vaushell.superpipes.nodes.A_Node.java
/** * Send actual message to every connected nodes. * * @throws java.lang.Exception// www. j a va2 s. c o m */ protected void sendMessage() throws Exception { if (message == null) { throw new IllegalArgumentException("Message is not set"); } if (LOGGER.isTraceEnabled()) { LOGGER.trace("[" + getNodeID() + "] sendMessage : message=" + Message.formatSimple(message)); } Message result = message; for (final A_Transform transform : transformsOUT) { result = transform.transform(result); if (result == null) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("[" + getNodeID() + "] send but discard message=" + Message.formatSimple(message)); } return; } else { result = SerializationUtils.clone(result); } } if (LOGGER.isDebugEnabled()) { LOGGER.debug("[" + getNodeID() + "] send message=" + Message.formatSimple(message)); } dispatcher.sendMessage(nodeID, result); }
From source file:com.github.dozermapper.core.functional_tests.InheritanceMappingTest.java
@Test public void testComplexSuperClassMapping() { mapper = getMapper("mappings/testDozerBeanMapping.xml"); SubClass obj = testDataFactory.getSubClass(); SubClassPrime objPrime = mapper.map(obj, SubClassPrime.class); SubClass obj2 = mapper.map(objPrime, SubClass.class); SubClassPrime objPrime2 = mapper.map(obj2, SubClassPrime.class); assertEquals("" + obj.getCustomConvert().getAttribute().getTheDouble(), obj2.getCustomConvert().getAttribute().getTheDouble() + ""); // one-way mapping objPrime.setSuperFieldToExcludePrime(null); assertEquals(objPrime, objPrime2);/* w ww .jav a2 s.c o m*/ // Pass by reference obj = testDataFactory.getSubClass(); SubClass subClassClone = SerializationUtils.clone(obj); objPrime = mapper.map(obj, SubClassPrime.class); mapper.map(objPrime, obj); obj.setCustomConvert(null); subClassClone.setCustomConvert(null); // more objects should be added to the clone from the ArrayList TheFirstSubClass fsc = newInstance(TheFirstSubClass.class); fsc.setS("s"); subClassClone.getTestObject().getHintList().add(fsc); subClassClone.getTestObject().getHintList().add(fsc); subClassClone.getTestObject().getEqualNamedList().add("1value"); subClassClone.getTestObject().getEqualNamedList().add("2value"); int[] pa = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 }; int[] intArray = { 1, 1, 1, 1 }; Integer[] integerArray = { new Integer(1), new Integer(1), new Integer(1), new Integer(1) }; subClassClone.getTestObject().setAnArray(intArray); subClassClone.getTestObject().setArrayForLists(integerArray); subClassClone.getTestObject().setPrimArray(pa); subClassClone.getTestObject().setBlankDate(null); subClassClone.getTestObject().setBlankStringToLong(null); subClassClone.getSuperList().add("one"); subClassClone.getSuperList().add("two"); subClassClone.getSuperList().add("three"); // since we copy by reference the attribute copyByReference we need to null it out. The clone method above creates // two versions of it... // which is incorrect obj.getTestObject().setCopyByReference(null); subClassClone.getTestObject().setCopyByReference(null); obj.getTestObject().setCopyByReferenceDeep(null); subClassClone.getTestObject().setCopyByReferenceDeep(null); obj.getTestObject().setGlobalCopyByReference(null); subClassClone.getTestObject().setGlobalCopyByReference(null); // null out string array because we get NPE since a NULL value in the String [] obj.getTestObject().setStringArrayWithNullValue(null); subClassClone.getTestObject().setStringArrayWithNullValue(null); subClassClone.getTestObject().setExcludeMeOneWay("excludeMeOneWay"); assertEquals(subClassClone, obj); }
From source file:com.github.dozermapper.core.functional_tests.MapperTest.java
@Test public void testDeepProperties() { House src = testDataFactory.getHouse(); HomeDescription dest = mapper.map(src, HomeDescription.class); House src2 = mapper.map(dest, House.class); HomeDescription dest2 = mapper.map(src2, HomeDescription.class); long[] prim = { 1, 2, 3, 1, 2, 3 }; // cumulative relationship dest.setPrim(prim);//from w w w. ja v a 2s. com assertEquals(dest, dest2); // By reference src = testDataFactory.getHouse(); House houseClone = SerializationUtils.clone(src); dest = mapper.map(src, HomeDescription.class); mapper.map(dest, src); // cumulative relationship int[] prims = { 1, 2, 3, 1, 2, 3 }; houseClone.getOwner().setPrim(prims); // add two more rooms Room room1 = new Room(); room1.setName("Living"); Room room2 = new Room(); room2.setName("kitchen"); Van van = new Van(); van.setName("van2"); houseClone.getRooms().add(room1); houseClone.getRooms().add(room2); houseClone.getCustomSetGetMethod().add(van); assertEquals(houseClone, src); }
From source file:com.mirth.connect.plugins.datapruner.DataPruner.java
@Override public void run() { try {//from w w w .j a v a2s . c o m logger.debug("Executing pruner, started at " + new SimpleDateFormat("MM/dd/yyyy hh:mm aa").format(Calendar.getInstance().getTime())); if (pruneEvents) { pruneEvents(); } String date = new SimpleDateFormat(MessageWriterFactory.ARCHIVE_DATE_PATTERN) .format(Calendar.getInstance().getTime()); String archiveFolder = (archiveEnabled) ? archiverOptions.getRootFolder() + IOUtils.DIR_SEPARATOR + date : null; Queue<PrunerTask> taskQueue; try { taskQueue = buildTaskQueue(); } catch (Exception e) { // the error should already be logged return; } logger.debug("Pruner task queue built, " + taskQueue.size() + " channels will be processed"); Map<String, String> attributes = new HashMap<String, String>(); if (taskQueue.isEmpty()) { attributes.put("No messages to prune.", ""); eventController.dispatchEvent(new ServerEvent(serverId, DataPrunerService.PLUGINPOINT, Level.INFORMATION, Outcome.SUCCESS, attributes)); } while (!taskQueue.isEmpty()) { ThreadUtils.checkInterruptedStatus(); PrunerTask task = taskQueue.poll(); try { status.setCurrentChannelId(task.getChannelId()); status.setCurrentChannelName(task.getChannelName()); status.setTaskStartTime(Calendar.getInstance()); PruneResult result = pruneChannel(task.getChannelId(), task.getChannelName(), task.getMessageDateThreshold(), task.getContentDateThreshold(), archiveFolder, task.isArchiveEnabled()); status.getProcessedChannelIds().add(task.getChannelId()); attributes.put("Channel ID", task.getChannelId()); attributes.put("Channel Name", task.getChannelName()); if (archiveEnabled && task.isArchiveEnabled()) { attributes.put("Messages Archived", Long.toString(result.numMessagesArchived)); } attributes.put("Messages Pruned", Long.toString(result.numMessagesPruned)); attributes.put("Content Rows Pruned", Long.toString(result.numContentPruned)); attributes.put("Time Elapsed", getTimeElapsed()); eventController.dispatchEvent(new ServerEvent(serverId, DataPrunerService.PLUGINPOINT, Level.INFORMATION, Outcome.SUCCESS, attributes)); } catch (InterruptedException e) { throw e; } catch (Exception e) { status.getFailedChannelIds().add(task.getChannelId()); attributes.put("channel", task.getChannelName()); attributes.put("error", e.getMessage()); attributes.put("trace", ExceptionUtils.getStackTrace(e)); eventController.dispatchEvent(new ServerEvent(serverId, DataPrunerService.PLUGINPOINT, Level.ERROR, Outcome.FAILURE, attributes)); Throwable t = e; if (e instanceof DataPrunerException) { t = e.getCause(); } logger.error("Failed to prune messages for channel " + task.getChannelName() + " (" + task.getChannelId() + ").", t); } finally { status.getPendingChannelIds().remove(task.getChannelId()); status.setCurrentChannelId(null); status.setCurrentChannelName(null); } } logger.debug("Pruner job finished executing"); } catch (InterruptedException e) { // We need to clear this thread's interrupted status, or else the EventController will fail to dispatch the event Thread.interrupted(); ServerEvent event = new ServerEvent(serverId, DataPrunerService.PLUGINPOINT + " Halted"); event.setLevel(Level.INFORMATION); event.setOutcome(Outcome.SUCCESS); eventController.dispatchEvent(event); logger.debug("Data Pruner halted"); } catch (Throwable t) { logger.error("An error occurred while executing the data pruner", t); } finally { status.setEndTime(Calendar.getInstance()); lastStatus = SerializationUtils.clone(status); running.set(false); } }
From source file:com.link_intersystems.lang.reflect.Class2Test.java
@Test public void serializable() { Class2<?> genericDefinition = Class2.get(GenericClassWithBeanType.class); Class2<?> clone = (Class2<?>) SerializationUtils.clone(genericDefinition); TypeVariable<?> typeVariable = clone.getTypeVariable("BEAN_TYPE"); assertNotNull(typeVariable);// w w w . j a va 2 s . c om }
From source file:com.github.dozermapper.core.functional_tests.MapperTest.java
@Ignore("Failing after 4.3 release") @Test// w w w . jav a 2 s . co m public void testMapByReference() { // Map TestReferenceObject tro = newInstance(TestReferenceObject.class); TestReferenceFoo foo1 = newInstance(TestReferenceFoo.class); foo1.setA("a"); TestReferenceFoo foo = newInstance(TestReferenceFoo.class); foo.setA("a"); foo.setB(null); foo.setC("c"); List<TestReferenceFoo> list2 = newInstance(ArrayList.class); list2.add(foo); tro.setListA(list2); tro.setArrayToArrayCumulative(new Object[] { foo1 }); TestReferenceFoo foo2 = newInstance(TestReferenceFoo.class); foo2.setA("a"); foo2.setB(null); foo2.setC("c"); TestReferenceFoo foo3 = newInstance(TestReferenceFoo.class); foo3.setA("a"); foo3.setB(null); foo3.setC("c"); tro.setArrayToArrayNoncumulative(new Object[] { foo2 }); List<String> list3 = newInstance(ArrayList.class); list3.add("string1"); list3.add("string2"); tro.setListToArray(list3); int[] pa = { 1, 2, 3 }; tro.setPrimitiveArray(pa); Integer[] integerArray = { new Integer(1), new Integer(2) }; tro.setPrimitiveArrayWrapper(integerArray); Set<TestReferenceFoo> set = newInstance(HashSet.class); TestReferenceFoo foo4 = newInstance(TestReferenceFoo.class); foo4.setA("a"); set.add(foo4); tro.setSetToSet(set); Car car = new Car(); car.setName("myName"); tro.setCars(new Car[] { car }); Car car2 = new Car(); car2.setName("myName"); List<Car> vehicles = newInstance(ArrayList.class); vehicles.add(car2); tro.setVehicles(vehicles); TestReferenceObject toClone = SerializationUtils.clone(tro); TestReferencePrimeObject trop = mapper.map(tro, TestReferencePrimeObject.class); assertEquals("myName", (trop.getVans()[0]).getName()); assertEquals("myName", (trop.getMoreVans()[0]).getName()); TestReferenceFooPrime fooPrime = (TestReferenceFooPrime) trop.getListAPrime().get(0); fooPrime.setB("b"); TestReferenceFooPrime fooPrime2 = (TestReferenceFooPrime) trop.getArrayToArrayNoncumulative()[0]; fooPrime2.setB("b"); mapper.map(trop, tro); // make sure we update the array list and didnt lose the value 'c' - non-cumulative assertEquals("c", ((TestReferenceFoo) tro.getListA().get(0)).getC()); assertEquals("c", ((TestReferenceFoo) tro.getArrayToArrayNoncumulative()[0]).getC()); // cumulative toClone.setArrayToArrayCumulative(new Object[] { foo1, foo1 }); toClone.setCars(new Car[] { car, car }); Van van = new Van(); van.setName("myName"); toClone.getVehicles().add(van); // cumulative toClone.getListToArray().add("string1"); toClone.getListToArray().add("string2"); int[] paClone = { 1, 2, 3, 1, 2, 3 }; toClone.setPrimitiveArray(paClone); Integer[] integerArrayClone = { new Integer(1), new Integer(2), new Integer(1), new Integer(2) }; toClone.setPrimitiveArrayWrapper(integerArrayClone); assertEquals(toClone, tro); }
From source file:com.mirth.connect.plugins.datapruner.DataPruner.java
private void archiveAndGetIdsToPrune(Map<String, Object> params, String channelId, Calendar messageDateThreshold, String archiveFolder, PruneIds messageIds, PruneIds contentMessageIds) throws Throwable { String tempChannelFolder = archiveFolder + "/." + channelId; String finalChannelFolder = archiveFolder + "/" + channelId; try {/*from ww w . ja v a2 s. c o m*/ MessageWriterOptions messageWriterOptions = SerializationUtils.clone(archiverOptions); messageWriterOptions.setBaseFolder(System.getProperty("user.dir")); if (messageWriterOptions.getArchiveFormat() == null) { messageWriterOptions.setRootFolder(tempChannelFolder); } else { messageWriterOptions.setRootFolder(archiveFolder); messageWriterOptions.setArchiveFileName(channelId); } logger.debug("Running archiver, channel: " + channelId + ", root folder: " + messageWriterOptions.getRootFolder() + ", archive format: " + messageWriterOptions.getArchiveFormat() + ", archive filename: " + messageWriterOptions.getArchiveFileName() + ", file pattern: " + messageWriterOptions.getFilePattern()); numExported = 0; status.setArchiving(true); MessageWriter archiver = MessageWriterFactory.getInstance().getMessageWriter(messageWriterOptions, ConfigurationController.getInstance().getEncryptor()); AttachmentSource attachmentSource = null; if (messageWriterOptions.includeAttachments()) { attachmentSource = new AttachmentSource() { @Override public List<Attachment> getMessageAttachments(Message message) throws ClientException { return MessageController.getInstance().getMessageAttachment(message.getChannelId(), message.getMessageId()); } }; } long minMessageId = 0; try { List<Map<String, Object>> maps; do { ThreadUtils.checkInterruptedStatus(); SqlSession session = SqlConfig.getSqlSessionManager().openSession(true); try { params.put("minMessageId", minMessageId); maps = session.selectList("Message.getMessagesToPrune", params); } finally { session.close(); } List<Long> archiveMessageIds = new ArrayList<Long>(); Iterator<Map<String, Object>> iterator = maps.iterator(); while (iterator.hasNext()) { Map<String, Object> map = iterator.next(); long receivedDate = ((Calendar) map.get("mm_received_date")).getTimeInMillis(); long id = (Long) map.get("id"); if (messageDateThreshold != null && receivedDate < messageDateThreshold.getTimeInMillis()) { messageIds.add(id); } else { contentMessageIds.add(id); } minMessageId = id + 1; archiveMessageIds.add(id); if (archiveMessageIds.size() == archiverBlockSize || !iterator.hasNext()) { ThreadUtils.checkInterruptedStatus(); DonkeyDao dao = getDaoFactory().getDao(); try { List<Message> messages = dao.getMessages(channelId, archiveMessageIds); for (Message message : messages) { if (attachmentSource != null) { List<Attachment> attachments = attachmentSource .getMessageAttachments(message); if (CollectionUtils.isNotEmpty(attachments)) { message.setAttachments(attachments); } } if (archiver.write(message)) { numExported++; } } archiveMessageIds.clear(); } finally { dao.close(); } } } } while (maps != null && maps.size() == ID_RETRIEVE_LIMIT); archiver.finishWrite(); } finally { archiver.close(); } if (messageWriterOptions.getArchiveFormat() == null && new File(tempChannelFolder).isDirectory()) { try { FileUtils.moveDirectory(new File(tempChannelFolder), new File(finalChannelFolder)); } catch (IOException e) { logger.error("Failed to move " + tempChannelFolder + " to " + finalChannelFolder, e); } } } catch (Throwable t) { FileUtils.deleteQuietly(new File(tempChannelFolder)); FileUtils.deleteQuietly(new File(finalChannelFolder)); throw t; } finally { status.setArchiving(false); } }
From source file:com.gargoylesoftware.htmlunit.WebTestCase.java
/** * A generics-friendly version of {@link SerializationUtils#clone(Serializable)}. * @param <T> the type of the object being cloned * @param object the object being cloned * @return a clone of the specified object */// w w w . j ava2 s. co m protected <T extends Serializable> T clone(final T object) { return SerializationUtils.clone(object); }
From source file:eu.crisis_economics.abm.model.ModelUtils.java
/** * Modify every instance of a parameter in the hierarchy of a configurator. * // w w w .j a va 2 s .c o m * @param on <br> * A configurator to modify. * @param parameterIdToFind <br> * The name of a parameter to search for. * @param substitute (<code>V</code>) <br> * The substitute (new value) to apply, if and when an instance of the parameter * is found. * @param doClone <br> * Whether or not <code>V</code> should be cloned for each substitution applied. * If this argument is <code>true</code>, <code>V</code> must be an instance of * {@link Serializable}. */ public static void apply(Object on, final String parameterIdToFind, Object substitute, boolean doClone) { final List<ConfigurationModifier> results = search(on, parameterIdToFind); for (ConfigurationModifier modifier : results) { if (doClone) modifier.set(SerializationUtils.clone((Serializable) substitute)); else modifier.set(substitute); } }
From source file:com.mirth.connect.client.ui.ChannelSetup.java
/** * Save all of the current channel information in the editor to the actual channel *///from w w w.j av a 2 s. c o m public boolean saveChanges() { if (!parent.checkChannelName(summaryNameField.getText(), currentChannel.getId())) { return false; } if (metadataPruningOnRadio.isSelected() && metadataPruningDaysTextField.getText().equals("")) { parent.alertWarning(parent, "If metadata pruning is enabled, the age of metadata to prune cannot be blank."); return false; } if (contentPruningDaysRadio.isSelected() && contentPruningDaysTextField.getText().equals("")) { parent.alertWarning(parent, "If content pruning is enabled, the age of content to prune cannot be blank."); return false; } if (metadataPruningOnRadio.isSelected() && contentPruningDaysRadio.isSelected()) { Integer metadataPruningDays = Integer.parseInt(metadataPruningDaysTextField.getText()); Integer contentPruningDays = Integer.parseInt(contentPruningDaysTextField.getText()); if (contentPruningDays > metadataPruningDays) { parent.alertWarning(parent, "The age of content to prune cannot be greater than the age of metadata to prune."); return false; } } // Store the current metadata column data in a map with the column name as the key and the type as the value. Map<String, MetaDataColumnType> currentColumns = new HashMap<String, MetaDataColumnType>(); for (MetaDataColumn column : currentChannel.getProperties().getMetaDataColumns()) { currentColumns.put(column.getName(), column.getType()); } Set<String> columnNames = new HashSet<String>(); for (int i = 0; i < metaDataTable.getRowCount(); i++) { DefaultTableModel model = (DefaultTableModel) metaDataTable.getModel(); // Do not allow metadata column names to be empty String columnName = (String) model.getValueAt(i, model.findColumn(METADATA_NAME_COLUMN_NAME)); if (StringUtils.isEmpty(columnName)) { parent.alertWarning(parent, "Empty column name detected in custom metadata table. Column names cannot be empty."); return false; } else { // Do not allow duplicate column names if (columnNames.contains(columnName)) { parent.alertWarning(parent, "Duplicate column name detected in custom metadata table. Column names must be unique."); return false; } if (columnName.equalsIgnoreCase("MESSAGE_ID") || columnName.equalsIgnoreCase("METADATA_ID")) { parent.alertWarning(parent, columnName + " is a reserved keyword and cannot be used as a column name in the custom metadata table."); return false; } // Add the column name to a set so it can be checked for duplicates columnNames.add(columnName); } MetaDataColumnType columnType = (MetaDataColumnType) model.getValueAt(i, model.findColumn(METADATA_TYPE_COLUMN_NAME)); // Remove columns from the map only if they have NOT been modified in a way such that their data will be deleted on deploy if (currentColumns.containsKey(columnName) && currentColumns.get(columnName).equals(columnType)) { currentColumns.remove(columnName); } } // Notify the user if an existing column was modified in a way such that it will be deleted on deploy if (!currentColumns.isEmpty()) { if (!parent.alertOption(parent, "Renaming, deleting, or changing the type of existing custom metadata columns\nwill delete all existing data " + "for that column. Are you sure you want to do this?")) { return false; } } boolean enabled = summaryEnabledCheckbox.isSelected(); saveSourcePanel(); if (parent.currentContentPage == transformerPane) { transformerPane.accept(false); transformerPane.modified = false; // TODO: Check this. Fix to prevent double save on confirmLeave } if (parent.currentContentPage == filterPane) { filterPane.accept(false); filterPane.modified = false; // TODO: Check this. Fix to prevent double save on confirmLeave } saveDestinationPanel(); MessageStorageMode messageStorageMode = MessageStorageMode.fromInt(messageStorageSlider.getValue()); String errorString = getQueueErrorString(messageStorageMode); if (errorString != null) { parent.alertWarning(parent, StringUtils.capitalize(errorString) + " queueing must be disabled first before using the selected message storage mode."); return false; } currentChannel.setName(summaryNameField.getText()); currentChannel.setDescription(summaryDescriptionText.getText()); updateScripts(); setLastModified(); currentChannel.getProperties().setClearGlobalChannelMap(clearGlobalChannelMapCheckBox.isSelected()); currentChannel.getProperties().setEncryptData(encryptMessagesCheckBox.isSelected()); currentChannel.getProperties().setInitialState((DeployedState) initialState.getSelectedItem()); currentChannel.getProperties().setStoreAttachments(attachmentStoreCheckBox.isSelected()); String validationMessage = checkAllForms(currentChannel); if (validationMessage != null) { enabled = false; // If there is an error on one of the forms, then run the // validation on the current form to display any errors. if (channelView.getSelectedComponent() == destination) { // If the destination is enabled... if (currentChannel.getDestinationConnectors().get(destinationTable.getSelectedModelIndex()) .isEnabled()) { destinationConnectorPanel.checkProperties(destinationConnectorPanel.getProperties(), true); } } else if (channelView.getSelectedComponent() == source) { sourceConnectorPanel.checkProperties(sourceConnectorPanel.getProperties(), true); } summaryEnabledCheckbox.setSelected(false); parent.alertCustomError(this.parent, validationMessage, CustomErrorDialog.ERROR_SAVING_CHANNEL); } // Set the channel to enabled or disabled after it has been validated currentChannel.setEnabled(enabled); saveChannelTags(); saveMetaDataColumns(); saveMessageStorage(messageStorageMode); saveMessagePruning(); // Update resource names parent.updateResourceNames(currentChannel); for (ChannelTabPlugin channelTabPlugin : LoadedExtensions.getInstance().getChannelTabPlugins().values()) { channelTabPlugin.getChannelTabPanel().save(currentChannel); } boolean updated = false; try { // Will throw exception if the connection died or there was an exception // saving the channel, skipping the rest of this code. updated = parent.updateChannel(currentChannel, parent.channelPanel.getCachedChannelStatuses().containsKey(currentChannel.getId())); try { currentChannel = (Channel) SerializationUtils.clone( parent.channelPanel.getCachedChannelStatuses().get(currentChannel.getId()).getChannel()); if (parent.currentContentPage == transformerPane) { if (channelView.getSelectedIndex() == SOURCE_TAB_INDEX) { transformerPane.reload(currentChannel.getSourceConnector()); } else if (channelView.getSelectedIndex() == DESTINATIONS_TAB_INDEX) { int destination = destinationTable.getSelectedModelIndex(); transformerPane.reload(currentChannel.getDestinationConnectors().get(destination)); } } if (parent.currentContentPage == filterPane) { if (channelView.getSelectedIndex() == SOURCE_TAB_INDEX) { filterPane.reload(currentChannel.getSourceConnector(), currentChannel.getSourceConnector().getFilter()); } else if (channelView.getSelectedIndex() == DESTINATIONS_TAB_INDEX) { Connector destination = currentChannel.getDestinationConnectors() .get(destinationTable.getSelectedModelIndex()); filterPane.reload(destination, destination.getFilter()); } } updateRevision(); updateLastModified(); } catch (SerializationException e) { parent.alertThrowable(this.parent, e); } } catch (ClientException e) { parent.alertThrowable(this.parent, e); } sourceConnectorPanel.updateQueueWarning(currentChannel.getProperties().getMessageStorageMode()); destinationConnectorPanel.updateQueueWarning(currentChannel.getProperties().getMessageStorageMode()); if (updated && saveGroupId != null) { parent.channelPanel.addChannelToGroup(currentChannel.getId(), saveGroupId); saveGroupId = null; } return updated; }