- Latest Versions
| Name | Version | Description |
|---|---|---|
| Cryptography | Crypto Keys | |
| Ming Ke Ming (名可名) | Decentralized User Identity Authentication | |
| Dao Ke Dao (道可道) | Universal Message Module | |
| DIMP (去中心化通讯协议) | Decentralized Instant Messaging Protocol |
extends CustomizedContent
/**
* Customized Content Processing Unit
* <p>
* Handle content for application customized
* </p>
*/
public class CustomizedContentProcessor extends BaseContentProcessor {
public CustomizedContentProcessor(Facebook facebook, Messenger messenger) {
super(facebook, messenger);
}
@Override
public List<Content> processContent(Content content, ReliableMessage rMsg) {
assert content instanceof CustomizedContent : "customized content error: " + content;
CustomizedContent customized = (CustomizedContent) content;
CustomizedContentFilter filter = SharedCustomizedFilter.customizedFilter;
// get handler for 'app' & 'mod'
CustomizedContentHandler handler = filter.filterContent(customized, rMsg);
if (handler == null) {
assert false : "should not happen";
return null;
}
// handle the action
Messenger messenger = getMessenger();
return handler.handleContent(customized, rMsg, messenger);
}
}- CustomizedContentHandler
/**
* Handler for Customized Content
*/
public interface CustomizedContentHandler {
/**
* Do your job
*
* @param content - customized content
* @param rMsg - network message
* @param messenger - message transceiver
* @return responses
*/
List<Content> handleContent(CustomizedContent content, ReliableMessage rMsg, Messenger messenger);
}/**
* Default Handler
*/
public class BaseCustomizedContentHandler implements CustomizedContentHandler {
public BaseCustomizedContentHandler() {
super();
}
@Override
public List<Content> handleContent(CustomizedContent content, ReliableMessage rMsg, Messenger messenger) {
//String app = content.getApplication();
String app = content.getString("app");
String mod = content.getModule();
String act = content.getAction();
return respondReceipt("Content not support.", rMsg.getEnvelope(), content, TwinsHelper.newMap(
"template", "Customized content (app: ${app}, mod: ${mod}, act: ${act}) not support yet!",
"replacements", TwinsHelper.newMap(
"app", app,
"mod", mod,
"act", act
)
));
}
//
// Convenient responding
//
protected List<Content> respondReceipt(String text, Envelope envelope, Content content, Map<String, Object> extra) {
// create base receipt command with text & original envelope
ReceiptCommand res = BaseContentProcessor.createReceipt(text, envelope, content, extra);
List<Content> responses = new ArrayList<>();
responses.add(res);
return responses;
}
}- CustomizedContentFilter
/**
* Filter for Customized Content Handler
*/
public interface CustomizedContentFilter {
/**
* Fetch a handler for 'app' and 'mod'
*
* @param content - customized content
* @param rMsg - message with envelope
* @return customized handler
*/
CustomizedContentHandler filterContent(CustomizedContent content, ReliableMessage rMsg);
}/**
* CustomizedContent Extensions
*/
public final class SharedCustomizedFilter {
public static CustomizedContentFilter customizedFilter = new AppCustomizedFilter();
}/**
* General CustomizedContent Filter
*/
public class AppCustomizedFilter implements CustomizedContentFilter {
private final Map<String, CustomizedContentHandler> handlers;
private final CustomizedContentHandler defaultHandler;
public AppCustomizedFilter() {
super();
handlers = new HashMap<>();
defaultHandler = new BaseCustomizedContentHandler();
}
public void setContentHandler(String app, String mod, CustomizedContentHandler handler) {
handlers.put(app + ":" + mod, handler);
}
protected CustomizedContentHandler getContentHandler(String app, String mod) {
return handlers.get(app + ":" + mod);
}
@Override
public CustomizedContentHandler filterContent(CustomizedContent content, ReliableMessage rMsg) {
//String app = content.getApplication();
String app = content.getString("app");
String mod = content.getModule();
CustomizedContentHandler handler = getContentHandler(app, mod);
if (handler != null) {
return handler;
}
// if the application has too many modules, I suggest you to
// use different handler to do the jobs for each module.
return defaultHandler;
}
}- Example for group querying
/* Command Transform:
+===============================+===============================+
| Customized Content | Group Query Command |
+-------------------------------+-------------------------------+
| "type" : i2s(0xCC) | "type" : i2s(0x88) |
| "sn" : 123 | "sn" : 123 |
| "time" : 123.456 | "time" : 123.456 |
| "app" : "chat.dim.group" | |
| "mod" : "history" | |
| "act" : "query" | |
| | "command" : "query" |
| "group" : "{GROUP_ID}" | "group" : "{GROUP_ID}" |
| "last_time" : 0 | "last_time" : 0 |
+===============================+===============================+
*/
public final class GroupHistoryHandler extends BaseCustomizedContentHandler {
@Override
public List<Content> handleContent(CustomizedContent content, ReliableMessage rMsg,
Messenger messenger) {
if (content.getGroup() == null) {
assert false : "group command error: " + content + ", sender: " + rMsg.getSender();
return respondReceipt("Group command error.", rMsg.getEnvelope(), content, null);
}
String act = content.getAction();
if (GroupHistory.ACT_QUERY.equals(act)) {
//assert GroupHistory.APP.equals(content.getApplication());
assert GroupHistory.MOD.equals(content.getModule());
return transformQueryCommand(content, rMsg, messenger);
}
assert false : "unknown action: " + act + ", " + content + ", sender: " + rMsg.getSender();
return super.handleContent(content, rMsg, messenger);
}
private List<Content> transformQueryCommand(CustomizedContent content, ReliableMessage rMsg,
Messenger messenger) {
Map<String, Object> info = content.copyMap(false);
info.put("type", ContentType.COMMAND);
info.put("command", QueryCommand.QUERY);
Content query = Content.parse(info);
if (query instanceof QueryCommand) {
return messenger.processContent(query, rMsg);
}
assert false : "query command error: " + query + ", " + content + ", sender: " + rMsg.getSender();
return respondReceipt("Query command error.", rMsg.getEnvelope(), content, null);
}
}
// void registerCustomizedHandlers() {
// AppCustomizedFilter filter = new AppCustomizedFilter();
// // 'chat.dim.group:history'
// filter.setContentHandler(
// GroupHistory.APP,
// GroupHistory.MOD,
// new GroupHistoryHandler()
// );
// SharedCustomizedFilter.customizedFilter = filter;
// }import chat.dim.Facebook;
import chat.dim.Messenger;
import chat.dim.protocol.ContentType;
import chat.dim.protocol.HandshakeCommand;
import chat.dim.protocol.group.QueryCommand;
public class ClientContentProcessorCreator extends BaseContentProcessorCreator {
public ClientContentProcessorCreator(Facebook facebook, Messenger messenger) {
super(facebook, messenger);
}
@Override
public ContentProcessor createContentProcessor(String msgType) {
switch (msgType) {
// application customized
case ContentType.APPLICATION:
case ContentType.CUSTOMIZED:
return new CustomizedContentProcessor(getFacebook(), getMessenger());
// ...
}
// others
return super.createContentProcessor(msgType);
}
@Override
public ContentProcessor createCommandProcessor(String type, String name) {
switch (name) {
case HandshakeCommand.HANDSHAKE:
return new HandshakeCommandProcessor(getFacebook(), getMessenger());
// ...
}
// others
return super.createCommandProcessor(type, name);
}
}To let your AppCustomizedProcessor start to work,
you must override BaseContentProcessorCreator for message types:
- ContentType.APPLICATION
- ContentType.CUSTOMIZED
and then set your creator for GeneralContentProcessorFactory in the MessageProcessor.