monikers



hi all,

Due to a nfs server breakdown, I could not send my mail this WE.
It happens that I just discovered how badly uni fucked me up
which means I will not implement the folowing ideas till 
mid-july: I have 1 month of crazyness ahead of me for my exams.

So, here is the non-finished proposal. (though the IDL is pretty 
perfect now ;)


BTW: Now that I am at this, I have to ask, once more why we do not 
implement size-negociation in bonobo through the interfaces but 
through GTK. If no one explains me this, I will commit a patch which
corrects this BUG. Which is a BUG. dot. It is EVIL to have the methods
and not implement them, leaving other implementors with nothing but 
using GTK. 
	-- This was a subliminal message to whoever removed 
	-- this implementation.

Mathieu


----------------------------------------------------------------
One more mail on Monikers.
Have fun. 

1) The interfaces.
2) The rationale.
	2.1 Important.
		2.1.1 get_object.
		2.1.2 parse_display_string.
		2.1.3 OAF Monikers.
	2.2 Less important. (But still ;)
3) The implementation.
4) Left issues.



1) The interfaces.
------------------

(heavily commented)

module Bonobo {


	/**
	 * Both of the folowing interfaces are there because
	 * they contain specific miniker methods which in
	 * my opinion should not be put into the otherwise
	 * perfect Embeddable and Container interfaces.
	 * However, the recent discussion on TypedStreams
	 * showed that some people (guess why ?) want to
	 * spoil beautiful interfaces to diminish the amount 
	 * of interfaces to implement.
	 */

	/**
	 * The LinkServer interface should be implemented by 
	 * applications which pretend they can be linkedto 
	 * from other applications. 
	 * They are a server to the other application.
	 * They can give away monikers and tehy can give away 
	 * the object corresponding to a certain moniker.
	 * Such servers should be able to answer QI on this 
	 * interface.
	 */
	LinkServer : Unknown {

		/**
		 * get_object is equivqlent ot the OLEE GetObject method.
		 * It allows a moniker to ask an application for a specific
		 * object it can provide.
		 * Example is : file.gnumeric#A2:A10 --> the "A2:A10" string
		 * is what would be asked to the application.
		 */
		Unknown get_object (in string object_name);


		/**
		 * parse_display_string is equivalent to OLE
		 * ParseDisplayName (string makes more sense to me)
		 * It should be called by the users who want the application
		 * to parse a Moniker string and get the moniker corresponding 
		 * to the string. Typically, this method will be called by our 
		 * magic API function which does magic string parsing for us.
		 * If the numberof parsed characters is not the size of the 
		 * string we passed to the method, we continue to parse
		 * by calling the re
		 */
		ItemMoniker  parse_display_string (in string moniker_string, out long parsed_chars); 

	};

	/**
	 * This interface should be implemented by the applications
	 * which use links. ie: which have links in their documents.
	 * The interface should be used by the default links dialog
	 * supposed to be shipped with bonobo which allows you to
	 * list all of the links of your opened document and allows 
	 * you to get them and repair them eventually by getting a
	 * relative or absolute moniker.
	 * Documents should be able to answer QI on this interface.
	 */
	LinkClient : Unknown {

		typedef sequence<Moniker> MonikerList

		/**
		 * returns the list of links in the document
		 * which implements this interface.
		 */
		MonikerList get_moniker_list ();

	};

	/**
	 * Moniker.
	 * Monilers should be able to answer QI
	 * on PersistStream in most cases.
	 */
	interface Moniker : Unknown {

		/**
		 * get_object is equivalent to OLE BindToObject.
		 * (the new name makes more sense to me)
		 * Should be called by applicatiosn which
		 * want to get the object the Moniker refers to.
		 * ie: they want to "bind" to the object.
		 * The leftMoniker parameter is especially important.
		 * See the discussion on this below this IDL.
		 */
		Unknown get_object (in Moniker leftMoniker);

// The method below is completely useless in my opinion.
//		Moniker parse_display_string (in string moniker_string, out long parsed_chars); 


		/**
		 * These 2 methods are supposed to be called by 
		 * LinkClient if need arises.
		 */
		Moniker get_relative_moniker ();
		Moniker get_absolute_moniker ();

		/**
		 * this method is redundant with QI because monikers
		 * MUST implement PersistStream and answer QI on it.
		 * It is there as a way to enforce the "MUST".
		 * Per Dirk-Jan idea.
		 */
		PersistStream get_persist_stream ();

		/**
		 * This method returns the complete string representing
		 * the moniker if you call it on a composite (which is
		 * what users SHOULD do). Otherwise, it will return the
		 * string representing a part of the moniker as a whole.
		 * actually, this method should return the same result as
		 * get_composite_string, get_oaf_string,
		 * get_url_string and get_item_string.
		 */
		string get_display_string ();
	};
	

	/**
	 * The folowing interfaces do implement the actual
	 * Monikers. They are needed to enforce IDL users
	 * the existance of the different kind of monikers
	 * which are not different in any any way except
	 * for their implementation of the IDL interfaces.
	 */
	interface CompositeMoniker : Moniker {
//		string get_composite_string ();
	}

	interface OAFMoniker : Moniker {
//		string get_oaf_string ();
	};

	interface URLMoniker : Moniker {
//		string get_url_string ();
	};

	interface ItemMoniker : Moniker {
//		string get_item_string ();
	};


};

2) The rationale.
-----------------

Well, the rationale behind most of the methods is not worth 
being discussed. If you do not understand it, you should 
try to read the Inside OLE book. 

However, I will discuss here the ideas behind the most 
important methods (LinkServer interface and Moniker::get_object)
and some less important ones (LinkClient and get_relative/absolute_moniker)

2.1 Important.
--------------

2.1.1 get_object.
-----------------

The folowing diagram (stolen from my old mail to this list)
outlines the structure of a Moniker.
-------------------------------------------------------
|                     Composite                       |
|               Left                        Right     |
| ---------------------------------      -----------  |
| |           Composite           |      | Item    |  |
| |     Left            Right     |      |         |  |
| |  -----------    -----------   |      | Moniker |  |
| |  |  File   |    |  Item   |   |      |         |  |
| |  | Moniker |    | Moniker |   |      -----------  |
| |  -----------    -----------   |                   |
| ---------------------------------                   |
-------------------------------------------------------

When you talk to a moniker, you will be talking to the outer
Composite Moniker. 

Imagine you have a pointer to a Composite moninker and call Moniker::get_object (
with OLE, you would have called Moniker::bind_to_object).
Here is the stacktrace you would have gotten:
Composite::get_object (NULL) ---- your call.
ItemMoniker::get_object (Left) ---- Composite tries to resolve
CompositeMoniker::get_object (NULL)
ItemMoniker::get_object (Left)
FileMoniker::get_object (NULL)

When the FileMoniker is asked to resolve, it activates the corresopnding 
application (thanks to OAF ;), QIs on PersistStorage, loads file, return
object from file.
the Right Item Moniker receives this object, QIs in LinkServer, calls
LinkServer::get_object, returns this object.
The inner Composite then returns this same object.
The outer Right ItemMoniker then QIs for LinkServer and calls
LinkServer::get_object. It then returns the object.
The outer composites receives this object and returns it.

Basically, the activation is taking place in the return phase of the 
recursive calls. What I just described is exactly what microsoft does ;)

So, this explains why we need the leftMoniker parameter to the
Moniker::get_object method.

The above also explains how the LinkServer::get_object method is used.

2.1.2 parse_display_string.
---------------------------

This method is quite important also.
In the previous simple example I presented, we have assumed that
the Monikers were built and I showed the basic algorithms used 
during the resolving phase. (hm... Me feeling is that 
Moniker::get_object should be called Moniker::resolve_to_object)

The LinkServer::parse_display_string is used to built the Monikers
which is why it is so important.

To build Monikers, we have the magic API function bonobo_moniker_from_string.
This API function is going to parse the string.

Oh, well, I am tried of writing all this down. Miguel knows how this works.

2.1.3 OAF Monikers.
-------------------

These Monikers were explained in my previous mail. They break 
the whole idea of Monikers encapsulating the resolving but they
seem to solve the pb of Maciej and I like them and you are not
obliged to use them: it is optional sugar ;)

OAFID:any-oaf-query-you-can-imagine#http://www.mathieu.org/myfile.gnumeric#A22:A78

so, you can make sure a certain OAF component is used to open the
corresponding file ;)


2.2 Less important. (But still ;)
-------------------

Just getting really tired for this.


3) The implementation.
----------------------

hm.... 
relatively simple.

LinkServer and LinkClient should be easy to implement.
Make the get_object generate a GETOBJECT signal 
(just like what it does right now ;)

Now, the Moniker should be implemented as a proxy GTK object, 
just like we did for the rest of Bonobo with the implementation 
methods being class methods of the GTK object. 
Then, we subclass this Object and implement 4 kinds of Monikers.
Then, we write our magic API call bonobo_moniker_from_string.
Then, we raise a V for Victory because we finally have it.

4) Left issues.
---------------

OAF Monikers need to be discussed. I like them a lot but I 
understand they break the whole idea of Monikers which is 
encapsulation.

Asynchronous Monikers must be thought upon.



-- 
Mathieu Lacage, mathieu@gnome.org
212 rue de tolbiac, 75013 Paris, FRANCE
http://www.advogato.org/person/mathieu




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]