Here is an example of a very simple model of the project metadata (modeled in UML):
It contains a class named Project, representing a project. The class may
or may not be a singleton depending on whether the IDE allows more
projects being open at the same time. A project is identified by a name
represented by name attribute inherited from Element abstract class. URL
attributes store the physical URL of the project file.
A project contains one to many classpaths (which is expressed using the
association line with a black diamond at the Project class denoting a
composite end). A classpath consists of zero to many classpath
elements.
After we saved the model to the UML XMI (Poseidon zargo file cantaining this model can be downloaded here) and converted it to the MOF XMI (the converted XMI can be downloaded here), we can load it into the MDR and generate the JMI interfaces from it. To do that, make sure that you have MDR modules installed. If so, you should see "MDR Browser" item under "View" menu:
Invoke the MDR Browser. Under the repository node, you should see MOF node, which represents a single instance of a MOF model (containing metadata conforming to MOF itself). It contains the definition of MOF itself. We can now "instantiate" MOF model contained in it to create an empty instance of MOF into which we will load our model of projects. To instantiate MOF, we need to right-click on the Model package of MOF and choose "Instantiate" action from the pop-up menu:
A dialog will appear asking for a name for the new instance - let's call it "Projects model". Now you can right-click on the newly created instance of MOF and import the projects model into it:
To generate interfaces from the projects model we can right-click on the newly imported Projects package under the "Projects model" node and choose "Generate JMI interfaces" from the pop-up menu.
Interfaces for managing and accessing the project metadata by other modules will be generated. For every class in the model two interfaces are generated - one representing a factory and the second representing individual instances. The factory interfaces contain methods for creating new instances of a given class and retrieving list of all existing instances. The instance interface then contains getter and setter methods for its attributes and references (i.e. association ends). Here are the interfaces generated from the Project class of the model:
Factory interface:
/** * Project class proxy interface. */ public interface ProjectClass extends javax.jmi.reflect.RefClass { /** * The default factory operation used to create an instance object. * @return The created instance object. */ public Project createProject(); /** * Creates an instance object having attributes initialized by the passed * values. * @param name * @param url * @return The created instance object. */ public Project createProject(java.lang.String name, java.lang.String url); }
Instance interface:
/** * Project object instance interface. */ public interface Project extends org.netbeans.jmi.projects.Element { /** * Returns the value of attribute url. * @return Value of attribute url. */ public java.lang.String getUrl(); /** * Sets the value of url attribute. See {@link #getUrl} for description on * the attribute. * @param newValue New value to be set. */ public void setUrl(java.lang.String newValue); /** * Returns the value of reference classPaths. * @return Value of reference classPaths. */ public java.util.Collection getClassPaths(); }
In addition one interface is generated for each association and package
in the model.
Implementation of all of these interfaces is provided by MDR during the
runtime automatically. All the metadata are stored and managed by MDR in
a pluggable storage (a b-tree database by default).
OK, so we have the interfaces now to access the metadata. Here is an example source code that creates a new project using the API:
package org.netbeans.mdrdemo; import org.netbeans.api.mdr.MDRManager; import org.netbeans.api.mdr.MDRepository; import org.netbeans.jmi.projects.*; public class ProjectCreationDemo { public static void main(String[] args) { // connect to the repository MDRepository repository = MDRManager.getDefault().getDefaultRepository(); // get the extent containing projects metadata (instance of // "Project" package in "Project model") ProjectsPackage extent = (ProjectsPackage) repository.getExtent("Projects metadata"); // get the factory for projects ProjectClass projectFactory = extent.getProject(); // create new project Project prj = projectFactory.createProject("MyProject", ""); // get the factory for class path ClassPathClass classPathFactory = extent.getClassPath(); // create new class path ClassPath cp = classPathFactory.createClassPath("Default"); // add the class path to the project cp.setProject(prj); // get the factory for class path element ClassPathElementClass cpElementFactory = extent.getClassPathElement(); // create new class path element ClassPathElement cpe1 = cpElementFactory.createClassPathElement("lib1.jar", ""); // add the element to the class path cpe1.setClassPath(cp); // create another class path element ClassPathElement cpe2 = cpElementFactory.createClassPathElement("lib2.jar", ""); // add the element to the class path cpe2.setClassPath(cp); } }
If you want to run the example above (and also the code below), you first need to do three things:
Here is a code that traverses the project metadata using the JMI API and writes it to the standard output:
package org.netbeans.mdrdemo; import java.util.Iterator; import org.netbeans.api.mdr.MDRManager; import org.netbeans.api.mdr.MDRepository; import org.netbeans.jmi.projects.*; public class ProjectRetrievalDemo { public static void main(String[] args) { // connect to the repository MDRepository repository = MDRManager.getDefault().getDefaultRepository(); // get the extent containing projects metadata ProjectsPackage extent = (ProjectsPackage) repository.getExtent("Projects metadata"); // get the factory for projects ProjectClass projectFactory = extent.getProject(); // get list of all projects for (Iterator it = projectFactory.refAllOfClass().iterator(); it.hasNext();) { Project prj = (Project) it.next(); // print the project name System.out.println("Found project: " + prj.getName()); // print out the classpaths in the project System.out.println("It contains the following class paths:"); for (Iterator it2 = prj.getClassPaths().iterator(); it2.hasNext();) { ClassPath cp = (ClassPath) it2.next(); // print the class path name System.out.print(" " + cp.getName() + " = "); // print out the class path elements for (Iterator it3 = cp.getElements().iterator(); it3.hasNext();) { ClassPathElement cpe = (ClassPathElement) it3.next(); // print the class path element name System.out.print(cpe.getName() + "; "); } System.out.println(); } } } }
When a user wants to open a different set of projects, the current projects metadata can be saved to an XML file and replaced by the metadata for the new set of projects in the repository. Saving the metadata is very simple and can be done by a single call to XMIWriter class:
XMIWriterFactory.getDefault().createXMIWriter().write(outputstream, extent, xmiVersion);
The produced XML file will look like the following:
<?xml version = '1.0' encoding = 'ISO-8859-1' ?> <XMI xmi.version = '1.2' timestamp = 'Wed Sep 17 21:20:34 CEST 2003'> <XMI.header> <XMI.documentation> <XMI.exporter>Netbeans XMI Writer</XMI.exporter> <XMI.exporterVersion>1.0</XMI.exporterVersion> </XMI.documentation> </XMI.header> <XMI.content> <Projects.Project xmi.id = 'a1' name = 'MyProject' url = ''> <Projects.Project.classPaths> <Projects.ClassPath xmi.id = 'a2' name = 'Default'> <Projects.ClassPath.elements> <Projects.ClassPathElement xmi.id = 'a3' name = 'lib1.jar' url = ''/> <Projects.ClassPathElement xmi.id = 'a4' name = 'lib2.jar' url = ''/> </Projects.ClassPath.elements> </Projects.ClassPath> </Projects.Project.classPaths> </Projects.Project> </XMI.content> </XMI>
To load the project metadata back into the MDR from the XMI file, one just needs to make a call to XMI reader:
XMIReaderFactory.getDefault().createXMIReader().read(inputstream, null, extent);