XWiki Android Project
Description
This page is for future development and ideas about XWiki Android tools.
See current state at Google Android Client.
[1] Introduction
Google Android XWiki Connector was the first step towards XWiki mobility through android platform. Here the Idea is to improve it as a XWiki Android mobile Platform where developers can build their own applications on top of it.
This is the continuation of the project: http://extensions.xwiki.org/xwiki/bin/view/Extension/Google+Android+Client
[2] Project architecture
[3] Introduction to architectural components.
Xwiki RESTful Connector
a) ReST Connector
This layer is concerned with communicating with the XWiki server instance via REST.
For further detail on the low level API provided by this component see http://extensions.xwiki.org/xwiki/bin/view/Extension/Google+Android+Client
![]() |
Above module abstract the XWiki Restful API documented here http://platform.xwiki.org/xwiki/bin/view/Features/XWikiRESTfulAPI .
b) ReST models
Contains models representing Xwiki RESTful resources such as Page element, Object element and etc. XML RESTful communication is supported by xwiki-rest-model-simple-xml. ( http://extensions.xwiki.org/xwiki/bin/view/Extension/Google+Android+Client )
C ) RAL
Rest Access Layer. This is a simplified model for accessing XWiki RESTful API. Strips down all the fine grained calls of XWiki RESTful API to simple CRUD (Create, Retreive, Update, Delete) operations. Making the programming model much more simple. The RAL module supports CRUD operations only for the main first class entities which are Document, Space, Wiki.
d) Transformation
This component is used for transforming the Xwiki Domain Model into underlying Xwiki Rest Model for communication with the server.
Domain Model
a) Xwiki Domain Model
This is a representation of the XWiki Domain model. It represents Domain objects for Wiki, Spaces, Document, and Attachments etc.Mobile version of XWiki module "model". Also represents the Xwik Class, Object, Properties model. Refer http://platform.xwiki.org/xwiki/bin/view/DevGuide/DataModel for Xwiki data model.
These model entities can directly be transformed to android RESTful model and thus be used to manipulate the state of the server. Ex: a Document object in the XA(XWiki Android) is same as that in XE. So a Document object that is created in the client application can be directly send to the server through the RAL so that it will be created in the server as well.
b) Xwiki Android Entities
This contains model entities wich are not directly adopted from Xwiki Enterprise Domain mode. Represents entities such as User, AuditEntry etc.
These entities do not have a direct mapping with the Domain model of the server. These entities are there to represent XWiki Android specific data model.
File Store
The File Store is the module that allows persistence for XWiki Domain model objects. For example you can directly save a Xwiki Document object in to the android device through the file store apis.
Contains APIs for saving, loading, deleting, listing all Xwiki Domain Entities in the device. This module is designed with Data Access Object Pattern offering objects named as Fao(File Access Objects). When a Xwiki model object like document is in need to be persisted we can use a Fao to save it to the device. The file store implementation saved the entity as a file in the device and keeps a lightweight reference to the saved entity in the SQLite database .
DAL
The Data Access Layer provides functionality to persist XWiki Android Entities in to the SQLite Database. The API is very simple to use as this layer provides simple Object to Relational mapping through Data Access Objects.
Base Services
These are simply business facades that simplify the usage of underlying APIs such as RAL, FAL, DAL.
The base services provide service functionality as follows.
a) Xwiki Model Remote Services,
Ex: Create, Retreive ,Querry, Update and Delete services for Documents.
b) Xwiki Model Local Services
Ex: Save, Load, List saved documents and Delete services for Documents.
c) Xwiki Common Services
Ex: Login service .
App Specific Services
These services use the Base services. But are specific for each application. For example if you are creating a blog application there are blog application specific features that need to be implemented. The Android activities can directly use the Base services but implementing them as a separate layer will lead to a cleaner design.
Xwiki Application Context
This is one of the core parts of the architecture. The XWiki Application Context is used for simple IoC. The control of constructing EntityManagers(DAL layer), FileStoreManagers( FAL layer) and other major components are given to the Application Context.
Sync
Provides APIs for automatically syncing XWiki Domain Model state on the device with that in the remote Server.
For example this API can be used to automatically sync a Document when the user could not upload it to the server due to connectivity issues.
Security and Audit
Packs functionality for encrypting and auditing user activities.
[4] API Usage
1) How to create a Document.
import org.xwiki.android.blog.xobj.XBlogPost;
import org.xwiki.android.ral.RaoException;
import org.xwiki.android.xmodel.entity.Document;
import org.xwiki.android.xmodel.entity.Document;
import org.xwiki.android.xmodel.svc.DocumentRemoteSvcCallbacks;
import org.xwiki.android.xmodel.svc.DocumentRemoteSvcs;
import org.xwiki.android.xmodel.svc.DocumentSvcImpl;
...
Document mydoc= new Document( "wikiName" , "spaceName" , "pageName" ); //create empty document
//lets make a Blog.BlogPostClass object to put into mydoc .
// in XA all model objects,classes, properties are prefixed with X.
XBlogPost blgpstObj= new XBlogPost(); // Blog.BlogPostClass is know as ...blog.xobj.XBlogPost. Here we have removed
// the suffix Class and added a prefix X.
//lets edit some properties of the XBlogPost object
blgpstObj.setContent( "This blog post is created with Xwiki Android" );
mydoc.addObject(blgpstObj);
DocumentRemoteSvcs docsvc= new DocumentSvcImpl(); // the current implementation for DocumentRemoteSvcs is this.
// docsvc can be used to creat the document on the server. The service uses a seperate thread to do all the work.
//The results are given through a callback.
DocumentRemoteSvcCallbacks clbk= new DocumentRemoteSvcCallbacks()
{
@Override
public void onCreated(Document res, boolean success, RaoException ex)
{
if (success){
// update ui here. You can notify the user that the doc was created in the server.
} else {
//you can check what the exception is and try to rectify .
//Most probably this same document is already existing in the server. So you should delete
//the already existing one and recreate. Or you can do a simple update by docsvc.update( mydoc , clbk );
}
}
};
docsvc.create(mydoc,clbk); // ok the docsvc does all the work of creating a page for the document and then adding
// all those objects,tags,comments and attachments in the document.
...
2) Advanced manipulation of XObjects.
import org.xwiki.android.blog.xobj.XBlogPost ;
import org.xwiki.android.xmodel.entity.Document;
import org.xwiki.android.xmodel.xobjects.XBooleanProperty ;
...
Document mydoc = new Document( "wikiName" , "spaceName" , "pageName" ); //create empty document
XBlogPost blgpstObj= new XBlogPost();
blgpstObj.setHidden( true ); //simple way to edit the value of "hidden" property of XBlogPost.
//say, now we want to do some advanced stuff with that property.
XBooleanProperty hiddenP= blgpstObj.getpHidden(); // use getp , setp methods to get the property.
//lets change hidden again.
hiddenP.setValue( false );
//change an attribute of the property.
hiddenP.setPrettyName( "Hidden pretty name" );
//Since a reference is passed, you do not have to blgpstObj.setpHidden(hiddenP) to commit the effects.
....
3) Save a Document
import org.xwiki.android.xmodel.entity.Document;
import org.xwiki.android.xmodel.svc.DocumentLocalSvcs;
import org.xwiki.android.xmodel.svc.DocumentSvcImpl;
....
Document mydoc= new Document( "wikiName" , "spaceName" , "pageName" ); //create empty document
// ... edit mydoc
//lets save it!
DocumentLocalSvcs docsvcl= new DocumentSvcImpl();
docsvcl.save(mydoc, "My tag to identify this easily" , null ); //docsvcl.save(doc, tag, clbk ). we pass null for clbk
// since we do not want to know wether the doc was sucessfully
// saved or not.
....
4] Save Document and get notified of the save completion.
import java.io.File;
import org.xwiki.android.xmodel.entity.Document;
import org.xwiki.android.xmodel.svc.DocumentLocalSvcCallbacks;
import org.xwiki.android.xmodel.svc.DocumentLocalSvcs;
import org.xwiki.android.xmodel.svc.DocumentSvcImpl;
...
Document mydoc= new Document( "wikiName" , "spaceName" , "pageName" ); //create empty document
// ... edit mydoc
DocumentLocalSvcs docsvcl= new DocumentSvcImpl();
DocumentLocalSvcCallbacks clbk = new DocumentLocalSvcCallbacks()
{
@Override
public void onSaveComplete(File savedto)
{
if (savedto!= null ){
//success. Edit UI to notify user here.
} else {
//oops problem. May be the device storage is full.
}
}
};
docsvcl.save(mydoc, "My tag to identify this easily" , null );
...
5] List and Load documents in File Store
import java.util.List;
import java.util.Map;
import org.xwiki.android.fileStore.FSDocumentReference;
import org.xwiki.android.xmodel.entity.Document;
import org.xwiki.android.xmodel.svc.DocumentLocalSvcCallbacks;
import org.xwiki.android.xmodel.svc.DocumentLocalSvcs;
import org.xwiki.android.xmodel.svc.DocumentSvcImpl;
import android.app.Activity;
public class _05_ListAndLoadDocuments extends Activity
{
FSDocumentReference loadMe ;
DocumentLocalSvcs ds ;
protected void onCreate(android.os.Bundle savedInstanceState)
{
ds = new DocumentSvcImpl();
DocumentLocalSvcCallbacks clbk1 = new DocumentLocalSvcCallbacks()
{
@Override
public void onListingComplete(List<FSDocumentReference> rslts, Map<String, Object> matchedby)
{
// matched by will contain entry ("space", "MySpace")
loadMe = rslts.get(0);
loadThis( loadMe );
}
};
ds .listBySpace( "MySpace" , clbk1);
// after the listing is complete you will be notified in the onListingComplete.
}
private void loadThis(FSDocumentReference ref)
{
DocumentLocalSvcCallbacks clbk2 = new DocumentLocalSvcCallbacks()
{
@Override
public void onLoadComplete(Document entity)
{
//entity is the loaded document.
}
};
ds .load(ref, clbk2);
}
}