Magento2: add custom quote extension attribute - magento2

I am trying to add an extension attribute to a quote through a custom REST API, and I would like to retrieve this info later.
But when I try to get the value, is always null.
The code will explain better than me.
etc/di.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
[...]
<preference for="Wow\Orderplatform\Api\Data\CartInterface"
type="Wow\Orderplatform\Model\Cart" />
</config>
etc/extension_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\CartInterface">
<attribute code="order_platform" type="Wow\Orderplatform\Api\Data\CartInterface"/>
</extension_attributes>
</config>
CartInterface
interface CartInterface extends ExtensibleDataInterface
{
const ORDER_PLATFORM = 'order_platform';
/**
* Retrieve order platform
*
* #return string
*/
public function getOrderPlatform();
/**
* Set order platform
*
* #param string $orderPlatform
* #return $this
*/
public function setOrderPlatform($orderPlatform);
}
The implementation:
class Cart extends AbstractExtensibleModel implements CartInterface
{
/**
* {inheritdoc}
*/
public function getOrderPlatform()
{
return $this->getData(self::ORDER_PLATFORM);
}
/**
* {inheritdoc}
*/
public function setOrderPlatform($orderPlatform)
{
return $this->setData(self::ORDER_PLATFORM, $orderPlatform);
}
}
I try to save the extension attribute in a REST API:
$quote = $this->quoteRepository->getActive($cartId);
$extensions = $quote->getExtensionAttributes();
$platformExt = $this->wowCartExtInterfaceFactory->create();
$platformExt->setOrderPlatform($platform);
$extensions->setOrderPlatform($platformExt);
$quote->setExtensionAttributes($extensions);
$this->quoteRepository->save($quote);
No errors in this procedure.
The problem is that I am not able to get back the value from the quote:
$quote = $this->quoteRepository->getActive($cartId);
$extensions = $quote->getExtensionAttributes();
$extensions->getOrderPlatform(); // Always null
Any hints?
Thanks

This is core bug in magento2 tried to do same for some requirement and found
Join extension attributes are not adding to quote results
There seems to be an issue with join extension attributes as per my debugging
ex.
<extension_attributes for="Magento\Quote\Api\Data\CartItemInterface">
<attribute code="original_catalog_price" type="Magento\NegotiableQuote\Api\Data\NegotiableQuoteItemInterface" >
<join reference_table="negotiable_quote_item" reference_field="quote_item_id" join_on_field="item_id">
<field>original_catalog_price</field>
</join>
</attribute>
</extension_attributes>
Hopefully, the patch will release soon.

Related

How to store tags to custom entity?

I have custom entity and tag field defined as:
/**
* #ORM\ManyToMany(targetEntity="Sulu\Bundle\TagBundle\Tag\TagInterface")
* #ORM\JoinTable(name="venue_tags",
* joinColumns={#ORM\JoinColumn(name="venue_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="idTags", referencedColumnName="id")}
* )
*/
private $tags;
Then I have setter (adder actually) like this:
public function addTag(TagInterface $tag)
{
$this->tags[] = $tag;
return $this;
}
Field is added to form details XML like:
<property name="tags" type="tag_selection">
<meta>
<title lang="de">Tags</title>
<title lang="en">Tags</title>
</meta>
<tag name="sulu.search.field" type="tags"/>
</property>
And inside my admin controller class I have mapping method:
protected function mapDataToEntity(array $data, Venue $entity): void
{
....
foreach ($data['tags'] as $tag) {
$entity->addTag($tag);
}
....
However as $data['tags'] I receive here array of string and my addTag() requires instance of TagInterface object. How can I create that object from string I have and generally is this the proper way for storing tags.
Update:
As #Johannes suggested added field:
/**
* #var TagManagerInterface
*/
private $tagManager;
and to constructor like:
public function __construct(
ViewHandlerInterface $viewHandler,
...
TagManagerInterface $tagManager
) {
$this->viewHandler = $viewHandler;
...
$this->tagManager = $tagManager;
parent::__construct($viewHandler);
}
And then trying to add tags like this:
$tagEntities = $this->tagManager->resolveTagNames($data['tags']);
foreach ($tagEntities as $tagEntity) {
$entity->addTag($tagEntity);
}
But then I get error:
Argument 1 passed to App\Entity\Venue::addTag() must implement interface Sulu\Bundle\TagBundle\Tag\TagInterface, int given, called in /var/www/html/src/Controller/Admin/VenueController.php on line 147
What I'm doing wrong? Like I'm getting tag ids? Should I load tags somehow?
Update 2:
After adding findById() saving tags works. However, now I found 2 more problems:
Even relations are saved well in database just after saving tags are not displayed any more in tags field. Also if I go to overview page and get back to edit entity selected (saved) tags are not re-populated. What else I have to add so saved tags in database would be used actually?
If I fist select "Tag1" and click "Save" it's saved well. But if I edit entity again and select "Tag1" again Sulu tries to create new row with same keys and I get error message: "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '4-1' for key 'venue_tags.PRIMARY'". I guess previously saved keys should be deleted first but how and where would be the optimal way?
You can use the TagManager service (id: sulu_tag.tag_manager or Sulu\Bundle\TagBundle\Tag\TagManagerInterface):
$tagIds = $tagManager->resolveTagNames($data['tags']);
foreach ($tagIds as $tagId) {
$entity->addTag($tagManager->findById($tagId));
}
For the record, I added to my entity new method:
public function removeAllTags()
{
foreach ($this->getTags() as $tag) {
$this->removeTag($tag);
}
}
which I'm calling from mapDataToEntity() before adding new tags:
$tagEntities = $this->tagManager->resolveTagNames($data['tags']);
$entity->removeAllTags();
foreach ($tagEntities as $tagEntity) {
$entity->addTag($this->tagManager->findById($tagEntity));
}
And this solves doubled keys but also solves tag removal potential issue.
Add following code to your class that should fix your first issue
/**
* #Serializer\VirtualProperty
* #Serializer\SerializedName("tags")
*/
public function getTagNameArray()
{
$tags = [];
foreach ($this->getTags() as $tag) {
$tags[] = $tag->getName();
}
return $tags;
}
To fix the second one you have to make the addTag method aware that you cannot have multiple relations to the same tag (check if the tag is already in the collection there).

Magento 2 Override Magento Checkout Model Cart updateItems function

I Need to Override updateItems function from \Magento\Checkout\Model\Cart
Also need to pass my custom helper class in __construct arguments . This is my __construct function of override class
namespace Vendor\Module\Model;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Checkout\Model\Session;
Class Cart extends \Magento\Checkout\Model\Cart
{
public function __construct(\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Checkout\Model\ResourceModel\Cart $resourceCart, Session $checkoutSession, \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, \Magento\CatalogInventory\Api\StockStateInterface $stockState, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, ProductRepositoryInterface $productRepository,
\Vendor\Module\Helper\Data $helper, array $data = []
)
{
$this->helper = $helper;
parent::__construct($eventManager, $scopeConfig, $storeManager, $resourceCart, $checkoutSession, $customerSession, $messageManager, $stockRegistry, $stockState, $quoteRepository, $productRepository, $data);
}
}
After this i run setup:upgrade,compile, static content deploy commands. Also remove all folders in var. But when i pass the argument in __construct function. It is not working. It displays blank page. When i remove my arguments from __construct function. then page is loading.
If you want to override updateItems from checkout cart model class then you must add preference in your module di.xml file, something like this:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Checkout\Model\Cart" type="[Vendor_Name]\[Module_Name]\Model\Cart" />
</config>
then, your custom module app/code/[Vendor_Name]/[Module_Name]/Model/Cart.php should look like this:
<?php
namespace [Vendor_Name]\[Module_Name]\Model;
use Magento\Checkout\Model\Cart as MagentoCart;
use [Vendor_Name]\[Module_Name]\Helper\Data;
class Cart extends MagentoCart
{
protected $helper;
public function __construct(Data $helper)
{
$this->helper = $helper;
}
// Code ...
}
then compile dependencies and that's all. Read this article to know more about Overriding classes in Magento 2

TYPO3 Extension developement: Attached objects of a relation aren't edited when the main record is

So currently i'm working on a TYPO3 extension using a Relation (1:n) to a specific class that provides objects to the main class. Let me explain a bit more in detail: I have a class, that next to normal properties, has a relation to a class that provides objects for some kind of checklist. The idea is that the FE user should be able to add new checklist entries, that's why i use that kind of concept. Initially it would look like this for the edit Action (the [x] represent that it's just a checklist):
main class
property of main class of type boolean [x]
attached object with a string and a boolean property [x]
attached object with a string and a boolean property [x]
property of main class of type text (for comments)
The FE user should be able to edit the record, so he should set the checklist entires to true or false, but even though the checklist entries appear, even those of the attached objects, they aren't persisted, only the properties of the main class are persisted when the FE user edits the records in the FE.
Here is my code:
The domain model of the main class (just the lines that specify the relation to the class that "provides" the objects). Keep in mind that few objects of the related class are attached to the main class when a record of the main class is created, the specific code just isn't in the main classe's controller...
/**
* zugewCheckobject
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\...\Kundentermine\Domain\Model\Checkobject>
* #cascade remove
*/
protected $zugewCheckobject = null;
public function __construct()
{
$this->zugewCheckobject = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Initializes all ObjectStorage properties
* Do not modify this method!
* It will be rewritten on each save in the extension builder
* You may modify the constructor of this class instead
*
* #return void
*/
protected function initStorageObjects()
{
$this->zugewCheckobject = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Adds a Checkobject
*
* #param \...\Kundentermine\Domain\Model\Checkobject $zugewCheckobject
* #return void
*/
public function addZugewCheckobject(\...\Kundentermine\Domain\Model\Checkobject $zugewCheckobject)
{
$this->zugewCheckobject->attach($zugewCheckobject);
}
/**
* Removes a Checkobject
*
* #param \...\Kundentermine\Domain\Model\Checkobject $zugewCheckobjectToRemove The Checkobject to be removed
* #return void
*/
public function removeZugewCheckobject(\...\Kundentermine\Domain\Model\Checkobject $zugewCheckobjectToRemove)
{
$this->zugewCheckobject->detach($zugewCheckobjectToRemove);
}
/**
* Returns the zugewCheckobject
*
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\...\Kundentermine\Domain\Model\Checkobject> $zugewCheckobject
*/
public function getZugewCheckobject()
{
return $this->zugewCheckobject;
}
/**
* Sets the zugewCheckobject
*
* #param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Unilab\Kundentermine\Domain\Model\Checkobject> $zugewCheckobject
* #return void
*/
public function setZugewCheckobject(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $zugewCheckobject)
{
$this->zugewCheckobject = $zugewCheckobject;
}
The edit and update Actions in the controller of the main class...
public function editAction(\...\Kundentermine\Domain\Model\Kaufmnnisch $kaufmnnisch)
{
$this->view->assign('kaufmnnisch', $kaufmnnisch);
}
/**
* action update
*
* #param \...\Kundentermine\Domain\Model\Kaufmnnisch $kaufmnnisch
* #return void
*/
public function updateAction(\...\Kundentermine\Domain\Model\Kaufmnnisch $kaufmnnisch)
{
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$checkobjectRepository = $objectManager->get(\...\Kundentermine\Domain\Repository\CheckobjectRepository::class);
foreach($kaufmnnisch->getZugewCheckobject() as $chk){
$checkobjectRepository->update($chk);
}
$this->kaufmnnischRepository->update($kaufmnnisch);
$this->redirect('list');
}
Part of the "edit" template. I pass the object "kaufmnnisch" as arguments to a partial of the class Chekobject (as it has objects of that class attached to it) and of course to a partial of the class Kaufmnnisch...
<f:section name="main">
<h1>Edit Kaufmnnisch</h1>
<f:flashMessages />
<f:render partial="FormErrors" arguments="{object:Kaufmnnisch}" />
<f:form action="update" name="kaufmnnisch" object="{kaufmnnisch}" >
<f:render partial="Checkobject/FormFields" arguments="{kaufmnnisch:kaufmnnisch}" />
<f:render partial="Kaufmnnisch/FormFields" arguments="{kaufmnnisch:kaufmnnisch}" />
<f:form.submit value="Save" />
</f:form>
</f:section>
Again: The problem is that only the properties of the main class get edited not those of the related objects. My assumption is that the Edit template or the partials aren't correctly set.
Edit: Here is the code for the partial of the Checkobject class that gets the object Kaufmnnisch as an argument passed.
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:for each="{kaufmnnisch.zugewcheckobject}" as="chk" >
<f:form.checkbox property="checked" value="0" /><br />
</f:for>
</html>
So basically "zugewcheckobject" is my object storage. Each checkbox gets rendered in the Edit template (thanks to the for each viewhelper), but the values for the boolean properties of each Checkobject object aren't persisted if the user clicks on the "save" button.
Edit2: A var_dump within the updateAction (within the foreach loop) reveals that the "Checked" property of each Checkobject object isn't changed, so it's not only not persisted, but the changed values aren't passed from the Edit template to the updateAction.
Edit3: Acessing every Checkobject object (here: $chk) via the objectstorage "zugewcheckobject" of the passed object of the class "Kaufmnnisch" in the Edit template is possible though, i just cant change the specific properties of the Checkobject objects, because JUST the Kaufmnnisch object is passed back to the updateAction of the specific controller, not each Checkobject of the objectstorage ("zugewcheckobject").
As i understand an objectstorage just contains references to its corresponding objects, not the objects themselfs, negating any changes that were made to them in the view.
In short: How can i also pass the corresponding objectstorage objects to the updateAction in one go for them to be persisted?
Edit4: It also doesn't seem to work with that solution...
<f:form action="update" name="kaufmnnisch" object="{kaufmnnisch}" >
<f:for each="{kaufmnnisch.zugewCheckobject}" as="chk" key="chkIndex" >
<f:form.hidden property="zugewCheckobject.{chkIndex}.__identity" value="{chk.uid}" />
<f:form.checkbox property="zugewCheckobject.{chkIndex}.checked" value="{chk.checked}" /><br />
</f:for>
<f:render partial="Kaufmnnisch/FormFields" arguments="{kaufmnnisch:kaufmnnisch}" />
<f:form.submit value="Save" />
</f:form>
The problem was solved here: TYPO3 extension thought experiment: Editing a news entry and the comment entries in one go?

update dynamically targeting provider in iPOJO

I have a component declared as:
<ipojo>
<component classname="HelloClass" name="helloCom" immediate="true">
<requires field="delayService" id="id1">
</requires>
</component>
<instance component="helloCom" name="hello">
<property name="requires.from">
<property name="id1" value="A"/>
</property>
</instance>
</ipojo>
The jar file of this component :helloComponent.jar
Now, i want to update (value="A") to (value="AA"). Thus, i implement a component using ConfigurationAdmin to update this property
public class ControllerReconfiguration {
private ConfigurationAdmin m_configAdmin;
#SuppressWarnings({ "rawtypes", "unchecked" })
public void reconfigure() throws IOException {
Configuration configuration = m_configAdmin.getConfiguration("hello","file:./helloComponent.jar");
configuration.setBundleLocation("file:./helloComponent.jar");
Properties props = new Properties();
//Dictionary props = new Hashtable();
props.put("id1", "AA");
configuration.update(props);
System.out.println("Update");
}
}
However, this ControllerReconfiguration component can't update the value 'A' (by 'AA') in 'hello' instance.
How to modify this ControllerReconfiguration component, please ?
Thanks you for your help.
Unfortunately, you can't push new 'from' configuration like this.
However, you can use the iPOJO introspection API directly: http://felix.apache.org/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/using-ipojo-introspection-api.html
Retrieve the Architecture service of the instance
Retrieve the InstanceDescription and DependencyDescription
Call the setFilter method
Thanks Clement,
it works fine !!!!! :) I access InstanceManager using Factory.
Ex, in order to access InstanceManager of component "hello.call.CallHello"
#require
private Factory[] factories;
for (Factory factory : factories) {
/*
* "hello.call.CallHello" is a component name
* note: it is not component instance name
*/
if (factory.getName().equals("hello.call.CallHello")) {
/*
* a component can have many instances
* if there is only one instance.
* get(0) return the first instance.
*/
InstanceManager im = (InstanceManager) factory.getInstances().get(0);
}

How to perform an action after eclipse plugin is opened

I have an eclipse plugin and I want to perform certain action inside this plugin but after eclipse application is opened.
I tried to do it through overriding
public void postWindowCreate()
but it seems that I can't get inside this function when launching the application
Any ideas ?
Do you use e4? Then maybe the following link may help: http://www.eclipse.org/forums/index.php/m/886197/
Edit:
OK, do you define your own application?
Are the methods provided by org.eclipse.ui.application.WorkbenchWindowAdvisor the ones you need? (e.g. preWindowOpen(), preWindowShellClose(), postWindowRestore(), postWindowCreate(), ...)
I also needed that functionality, so here's how I do it:
You need 3 classes, one implementing org.eclipse.equinox.app.IApplication e.g. MyApp, one which extends org.eclipse.ui.application.WorkbenchAdvisor e.g. MyAdvisor, and one which extends org.eclipse.ui.application.WorkbenchWindowAdvisor e.g. MyWindowAdvisor.
Then in MyApp you will probably call something like
PlatformUI.createAndRunWorkbench(display, new MyAdvisor());
where you actually start the workbench and provide your own WorkbenchWindowAdvisor. In MyAdvisor you have to overwrite:
#Override
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {
return new MyWindowAdvisor(configurer);
}
in which you provide your WorkbenchWindowAdvisor. In class MyWindowAdvisor you can finally override the appropriate functions, e.g.
#Override
public void postWindowOpen() {
//TODO
}
Of course you have to run the appropriate application for this to work ;)
OK, now, to provide arbitrary plug-ins to deal with these events, you could define an extension point.
First you need an interface which defines the "events" you want to listen to, e.g.:
public interface IWorkbenchWindowAdvisorHook
{
/**
* Performs arbitrary actions before the window is opened.
* <p>
* This method is called before the window's controls have been created.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* Typical clients will use the window configurer to tweak the
* workbench window in an application-specific way; however, filling the
* window's menu bar, tool bar, and status line must be done in
* {#link ActionBarAdvisor#fillActionBars}, which is called immediately
* after this method is called.
* </p>
*/
void preWindowOpen();
/**
* Performs arbitrary actions as the window's shell is being closed
* directly, and possibly veto the close.
* <p>
* This method is called from a ShellListener associated with the window,
* for example when the user clicks the window's close button. It is not
* called when the window is being closed for other reasons, such as if the
* user exits the workbench via the {#link ActionFactory#QUIT} action.
* Clients must not call this method directly (although super calls are
* okay). If this method returns <code>false</code>, then the user's
* request to close the shell is ignored. This gives the workbench advisor
* an opportunity to query the user and/or veto the closing of a window
* under some circumstances.
* </p>
*
* #return <code>true</code> to allow the window to close, and
* <code>false</code> to prevent the window from closing
* #see org.eclipse.ui.IWorkbenchWindow#close
* #see WorkbenchAdvisor#preShutdown()
*/
public boolean preWindowShellClose();
/**
* Performs arbitrary actions after the window has been restored,
* but before it is opened.
* <p>
* This method is called after a previously-saved window has been
* recreated. This method is not called when a new window is created from
* scratch. This method is never called when a workbench is started for the
* very first time, or when workbench state is not saved or restored.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* It is okay to call <code>IWorkbench.close()</code> from this method.
* </p>
*
* #exception WorkbenchException thrown if there are any errors to report
* from post-restoration of the window
*/
void postWindowRestore() throws WorkbenchException;
/**
* Performs arbitrary actions after the window has been created (possibly
* after being restored), but has not yet been opened.
* <p>
* This method is called after the window has been created from scratch,
* or when it has been restored from a previously-saved window. In the latter case,
* this method is called after <code>postWindowRestore</code>.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* </p>
*/
void postWindowCreate();
/**
* Performs arbitrary actions after the window has been opened (possibly
* after being restored).
* <p>
* This method is called after the window has been opened. This method is
* called after the window has been created from scratch, or when
* it has been restored from a previously-saved window.
* Clients must not call this method directly (although super calls are okay).
* The default implementation does nothing. Subclasses may override.
* </p>
*/
void postWindowOpen();
/**
* Performs arbitrary actions after the window is closed.
* <p>
* This method is called after the window's controls have been disposed.
* Clients must not call this method directly (although super calls are
* okay). The default implementation does nothing. Subclasses may override.
* </p>
*/
void postWindowClose();
}
Then the extension point schema (replace all "YOUR-xxx" with your own package/plug-in names, and namespace):
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="***YOUR-NAMESPACE***" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="***YOUR-PLUGIN***" id="workbenchWindowHook" name="***YOUR-PACKAGE***.workbenchWindowHook"/>
</appInfo>
<documentation>
An extension to actively hook into the WorkbenchWindowAdvisor&apos;s pre/post methods from other plug-ins.
This is primarily intended for plug-ins that are optional or restricted to some specific products.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="class" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="class">
<annotation>
<documentation>
The hook class implementing IWorkbenchWindowAdvisorHook.
</documentation>
</annotation>
<complexType>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
The hook class implementing IWorkbenchWindowAdvisorHook.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":***YOUR-PACKAGE***.IWorkbenchWindowAdvisorHook"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
</documentation>
</annotation>
</schema>
Then, in your MyWindowAdvisor you need to keep a reference to the extensions
// the reference list
private List<IWorkbenchWindowAdvisorHook> hooks = new ArrayList<IWorkbenchWindowAdvisorHook>();
load/initialize the extensions
//code for initializing the extensions, must be called in the constructor
private void initExtensions()
{
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(
IWorkbenchWindowAdvisorHook.ID);
for(IConfigurationElement element : config)
{
try
{
final Object o = element.createExecutableExtension("name"); //$NON-NLS-1$
if(o instanceof IWorkbenchWindowAdvisorHook)
{
hooks.add((IWorkbenchWindowAdvisorHook)o);
}
}
catch(CoreException e)
{
e.printStackTrace();
}
}
}
and in each "event" function call the extensions' methods:
// example method preWindowOpen()
public void preWindowOpen()
{
for(IWorkbenchWindowAdvisorHook hook : hooks)
{
try
{
hook.preWindowOpen();
}
catch(Throwable t)
{
CorePlugin.logDefaultError(t);
}
}
}
The final step is to provide an extension and class in each plug-in you need to listen to these workbench window events.