[jboss-svn-commits] JBL Code SVN: r29475 - in labs/jbossrules/trunk: drools-guvnor/src/main/java/org/drools/guvnor/client/rpc and 5 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sat Sep 26 01:05:11 EDT 2009


Author: jervisliu
Date: 2009-09-26 01:05:11 -0400 (Sat, 26 Sep 2009)
New Revision: 29475

Added:
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/LinkedAssetItem.java
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/LinkedAssetItemTest.java
Modified:
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.java
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.properties
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryService.java
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryServiceAsync.java
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/MetaDataWidget.java
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/NewAssetWizard.java
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/RepositoryServiceServlet.java
   labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/ServiceImplementation.java
   labs/jbossrules/trunk/drools-guvnor/src/test/java/org/drools/guvnor/server/ServiceImplementationTest.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItemIterator.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java
   labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java
   labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java
Log:
https://jira.jboss.org/jira/browse/GUVNOR-419: Sharable artifacts (eg one model, used in multiple packages)

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -1943,4 +1943,18 @@
 
     String AddRowBeforeSelectedRow();
     
+    String CreateNewAsset();
+    
+    String CreateLinkedAsset();
+    
+    String CreateLinkedAssetFromUUID();
+   
+    String NoteNewLinkedAsset();
+
+    String NewLinkedAssetDesc1();
+    
+    String NewLinkedAssetDesc2();
+    
+    String NewLinkedAssetDesc3();
+    
 }

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.properties
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.properties	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/messages/Constants.properties	2009-09-26 05:05:11 UTC (rev 29475)
@@ -923,4 +923,11 @@
 URLForDocumention=URL for package documentation:
 CanNotMoveColumnsFromOneTypeGroupToAnother=Can not move columns from one type group to another
 PleaseSelectARow=Please select a row
-AddRowBeforeSelectedRow=Add row before selected row...
\ No newline at end of file
+AddRowBeforeSelectedRow=Add row before selected row...
+CreateNewAsset=Create new: 
+CreateLinkedAsset=Create linked asset: 
+CreateLinkedAssetFromUUID=UUID of the existing asset: 
+NoteNewLinkedAsset=NOTE: 
+NewLinkedAssetDesc1=This will create a new asset that links to an existing one. To create a linked asset,
+NewLinkedAssetDesc2=you need to open the existing asset that you want to link to, copy and paste its 
+NewLinkedAssetDesc3=UUID to the text box above.

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryService.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryService.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryService.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -72,6 +72,13 @@
     public String createNewRule(String ruleName, String description, String initialCategory, String initialPackage, String format) throws SerializableException;
 
     /**
+     * Creates a new rule which refers to an existing rule.
+     * Return the UUID of the item created.
+     * This will not check in the rule, but just leave it as saved in the repo.
+     */
+    public String createNewLinkedRule(String ruleName, String linkedRuleUUID, String initialCategory, String initialPackage) throws SerializableException;
+
+    /**
      * Delete un checked in Asset
      */
     public void deleteUncheckedRule(String ruleName, String initialPackage);

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryServiceAsync.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryServiceAsync.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/rpc/RepositoryServiceAsync.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -43,6 +43,7 @@
 	public void loadTableConfig(java.lang.String p0, AsyncCallback<org.drools.guvnor.client.rpc.TableConfig> cb);
 	public void createCategory(java.lang.String p0, java.lang.String p1, java.lang.String p2, AsyncCallback<java.lang.Boolean> cb);
 	public void createNewRule(java.lang.String p0, java.lang.String p1, java.lang.String p2, java.lang.String p3, java.lang.String p4, AsyncCallback<java.lang.String> cb);
+	public void createNewLinkedRule(java.lang.String p0, java.lang.String p1, java.lang.String p2, java.lang.String p3, AsyncCallback<java.lang.String> cb);
 	public void deleteUncheckedRule(java.lang.String p0, java.lang.String p1, AsyncCallback cb);
 	public void clearRulesRepository(AsyncCallback cb);
 	public void listPackages(AsyncCallback<org.drools.guvnor.client.rpc.PackageConfigData[]> cb);

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/MetaDataWidget.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/MetaDataWidget.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/MetaDataWidget.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -183,7 +183,10 @@
                                            }
                                        },
                                        constants.DisableTip() ) );
-
+        
+        addAttribute( "UUID:",
+        		readOnlyText(uuid) );
+        
         endSection();
 
         startSection( constants.OtherMetaData() );

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/NewAssetWizard.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/NewAssetWizard.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/client/ruleeditor/NewAssetWizard.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -20,6 +20,7 @@
 import org.drools.guvnor.client.categorynav.CategoryExplorerWidget;
 import org.drools.guvnor.client.categorynav.CategorySelectHandler;
 import org.drools.guvnor.client.common.AssetFormats;
+import org.drools.guvnor.client.common.FormStyleLayout;
 import org.drools.guvnor.client.common.FormStylePopup;
 import org.drools.guvnor.client.common.GenericCallback;
 import org.drools.guvnor.client.common.LoadingPopup;
@@ -27,16 +28,21 @@
 import org.drools.guvnor.client.rpc.RepositoryServiceFactory;
 import org.drools.guvnor.client.rulelist.EditItemEvent;
 import org.drools.guvnor.client.messages.Constants;
+import org.drools.guvnor.client.modeldriven.brl.ISingleFieldConstraint;
 
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.ChangeListener;
 import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.TextArea;
 import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.core.client.GWT;
 import com.gwtext.client.util.Format;
@@ -50,6 +56,7 @@
     private Constants constants = GWT.create(Constants.class);
     
     private TextBox                name        = new TextBox();
+    private TextBox                linkedFromUUID        = new TextBox();
     private TextArea               description = new TextArea();
     private String                 initialCategory;
     
@@ -59,6 +66,9 @@
     private EditItemEvent afterCreate;
     private boolean showCats;
     private String format;
+    
+    private final FormStyleLayout newAssetLayout     = new FormStyleLayout();
+    private final FormStyleLayout linkedAssetLayout = new FormStyleLayout();
 
 
     /** This is used when creating a new rule. */
@@ -68,9 +78,36 @@
         this.format = format;
 
         this.afterCreate = afterCreate;
+        
+		RadioButton newPackage = new RadioButton("action", constants.CreateNewAsset()); // NON-NLS
+		RadioButton importPackage = new RadioButton("action", constants.CreateLinkedAsset()); // NON-NLS
+		newPackage.setChecked(true);
+		newAssetLayout.setVisible(true);
 
+		newPackage.addClickListener(new ClickListener() {
+			public void onClick(Widget w) {
+				newAssetLayout.setVisible(true);
+				linkedAssetLayout.setVisible(false);
+			}
+		});
+		linkedAssetLayout.setVisible(false);
+		importPackage.addClickListener(new ClickListener() {
+			public void onClick(Widget arg0) {
+				newAssetLayout.setVisible(false);
+				linkedAssetLayout.setVisible(true);
+			}
+		});
+		VerticalPanel ab = new VerticalPanel();
+		ab.add(newPackage);
+		ab.add(importPackage);
+		addAttribute("", ab);
 
-        addAttribute( constants.NameColon(), name );
+		addRow(newAssetLayout);
+		addRow(linkedAssetLayout); 
+			
+        
+		//layout for new asset.
+		newAssetLayout.addAttribute( constants.NameColon(), name );        	
 
         this.setAfterShow(new Command() {
 			public void execute() {
@@ -80,14 +117,14 @@
 
         if (showCats) {
 
-            addAttribute(constants.InitialCategory(), getCatChooser());
+        	newAssetLayout.addAttribute(constants.InitialCategory(), getCatChooser());
         }
 
         if (format == null) {
-            addAttribute(constants.TypeFormatOfRule(), this.formatChooser );
+        	newAssetLayout.addAttribute(constants.TypeFormatOfRule(), this.formatChooser );
         } else if (format == "*") { //NON-NLS
         	final TextBox fmt = new TextBox();
-        	addAttribute(constants.FileExtensionTypeFormat(), fmt);
+        	newAssetLayout.addAttribute(constants.FileExtensionTypeFormat(), fmt);
         	fmt.addChangeListener(new ChangeListener() {
 				public void onChange(Widget w) {
 					NewAssetWizard.this.format = fmt.getText();
@@ -95,7 +132,7 @@
         	});
         }
 
-        addAttribute(constants.Package() + ":", packageSelector);
+        newAssetLayout.addAttribute(constants.Package() + ":", packageSelector);
 
         description.setVisibleLines( 4 );
         description.setWidth( "100%" );
@@ -106,7 +143,7 @@
         	description.setText(constants.NewEnumDoco());
         }
 
-        addAttribute(constants.InitialDescription(), description);
+        newAssetLayout.addAttribute(constants.InitialDescription(), description);
 
         Button ok = new Button( constants.OK() );
         ok.addClickListener( new ClickListener() {
@@ -116,12 +153,40 @@
 
         } );
 
-        addAttribute( "", ok );
+        newAssetLayout.addAttribute( "", ok );
+        
+        //layout for create linked asset.
+        linkedAssetLayout.addAttribute( constants.NameColon(), name );        	
 
+        this.setAfterShow(new Command() {
+			public void execute() {
+				name.setFocus(true);			}
+        });
+        if (showCats) {
+        	linkedAssetLayout.addAttribute(constants.InitialCategory(), getCatChooser());
+        }
+        linkedAssetLayout.addAttribute(constants.Package() + ":", packageSelector);
+
+        linkedAssetLayout.addAttribute(constants.CreateLinkedAssetFromUUID(), linkedFromUUID );  
+        Button linkedAssetOKButton = new Button( constants.OK() );
+        linkedAssetOKButton.addClickListener( new ClickListener() {
+            public void onClick(Widget arg0) {
+                importOK();
+            }
+
+        } );
+        linkedAssetLayout.addAttribute( "", linkedAssetOKButton );
+        linkedAssetLayout.addRow( new HTML( "<br/><b>" + constants.NoteNewLinkedAsset() + "</b>" ) );
+        linkedAssetLayout.addRow( new HTML( constants.NewLinkedAssetDesc1() ) );
+        linkedAssetLayout.addRow( new HTML( constants.NewLinkedAssetDesc2() ) );
+        linkedAssetLayout.addRow( new HTML( constants.NewLinkedAssetDesc3() ) );
     }
 
+    public static Widget newImportWidget(final Command afterCreatedEvent,
+			final FormStylePopup parent) {
+		return null;
+	}
 
-
     private Widget getCatChooser() {
 
        Widget w = new CategoryExplorerWidget( new CategorySelectHandler() {
@@ -193,6 +258,41 @@
 
     }
 
+    /**
+     * When Import OK is pressed, it will update the repository with the imported rule.
+     */
+    void importOK() {
+
+        if (this.showCats && this.initialCategory == null) {
+			Window.alert(constants.YouHaveToPickAnInitialCategory());
+			return;
+		} else {
+			if (!validatePathPerJSR170(this.name.getText())) return;
+		}
+
+        GenericCallback cb = new GenericCallback() {
+            public void onSuccess(Object result) {
+            		String uuid = (String) result;
+            		if (uuid.startsWith("DUPLICATE")) { //NON-NLS
+            			LoadingPopup.close();
+            			Window.alert(constants.AssetNameAlreadyExistsPickAnother());
+            		} else {
+            			openEditor((String) result);
+            			hide();
+            		}
+            }
+        };
+
+
+        LoadingPopup.showMessage( constants.PleaseWaitDotDotDot() );
+        RepositoryServiceFactory.getService().createNewLinkedRule( name.getText(),
+        		                                                   linkedFromUUID.getText(),
+                                                          initialCategory,
+                                                          packageSelector.getSelectedPackage(),
+                                                          cb );
+
+    }
+
     private String getFormat() {
         if (format != null) return format;
         return formatChooser.getValue( formatChooser.getSelectedIndex() );
@@ -244,4 +344,5 @@
 		return true;
 	}
 
+	
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/RepositoryServiceServlet.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/RepositoryServiceServlet.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/RepositoryServiceServlet.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -121,6 +121,9 @@
 	public java.lang.String createNewRule(java.lang.String p0, java.lang.String p1, java.lang.String p2, java.lang.String p3, java.lang.String p4) throws com.google.gwt.user.client.rpc.SerializableException {
 		 return getService().createNewRule( p0,  p1,  p2,  p3,  p4);
 	}
+	public java.lang.String createNewLinkedRule(java.lang.String p0, java.lang.String p1, java.lang.String p2, java.lang.String p3) throws com.google.gwt.user.client.rpc.SerializableException {
+		 return getService().createNewLinkedRule( p0,  p1,  p2,  p3);
+	}	
 	public void deleteUncheckedRule(java.lang.String p0, java.lang.String p1)  {
 		getService().deleteUncheckedRule( p0,  p1);
 	}

Modified: labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/ServiceImplementation.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/ServiceImplementation.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/main/java/org/drools/guvnor/server/ServiceImplementation.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -253,8 +253,42 @@
 
     }
 
+    /**
+     * This will create a new asset which refers to an existing asset
+     */
     @WebRemote
     @Restrict("#{identity.loggedIn}")
+    public String createNewLinkedRule(String name,
+                                String linkedRuleUUID,
+                                String initialCategory,
+                                String initialPackage) throws SerializableException {
+        if ( Contexts.isSessionContextActive() ) {
+            Identity.instance().checkPermission( new PackageNameType( initialPackage ),
+                                                 RoleTypes.PACKAGE_DEVELOPER );
+        }
+
+        log.info( "USER:" + repository.getSession().getUserID() + " REFER to an existing asset name [" + linkedRuleUUID + "] in package [" + initialPackage + "]" );
+
+        try {
+
+            PackageItem pkg = repository.loadPackage( initialPackage );
+            AssetItem asset = pkg.addLinkedAsset( name, linkedRuleUUID, initialCategory);
+            repository.save();
+
+            return asset.getUUID();
+        } catch ( RulesRepositoryException e ) {
+            if ( e.getCause() instanceof ItemExistsException ) {
+                return "DUPLICATE";
+            } else {
+                log.error( e );
+                throw new SerializableException( e.getMessage() );
+            }
+        }
+
+    }
+    
+    @WebRemote
+    @Restrict("#{identity.loggedIn}")
     public void deleteUncheckedRule(String uuid,
                                     String initialPackage) {
         if ( Contexts.isSessionContextActive() ) {

Modified: labs/jbossrules/trunk/drools-guvnor/src/test/java/org/drools/guvnor/server/ServiceImplementationTest.java
===================================================================
--- labs/jbossrules/trunk/drools-guvnor/src/test/java/org/drools/guvnor/server/ServiceImplementationTest.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-guvnor/src/test/java/org/drools/guvnor/server/ServiceImplementationTest.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -79,8 +79,10 @@
 import org.drools.guvnor.server.repository.RepositoryStartupService;
 import org.drools.guvnor.server.repository.UserInbox;
 import org.drools.repository.AssetItem;
+import org.drools.repository.AssetItemIterator;
 import org.drools.repository.CategoryItem;
 import org.drools.repository.PackageItem;
+import org.drools.repository.RepositoryFilter;
 import org.drools.repository.RulesRepository;
 import org.drools.repository.RulesRepositoryException;
 import org.drools.repository.StateItem;
@@ -329,10 +331,193 @@
 
 		AssetItem dtItem = impl.repository.loadAssetByUUID(uuid);
 		assertEquals(dtItem.getDescription(), "an initial desc");
+	}	
 
+	public void testCreateLinkedAssetItem() throws Exception {
+		ServiceImplementation impl = getService();
+		PackageItem testCreateNewRuleAsLinkPackage1 = impl.repository.createPackage("testCreateNewRuleAsLinkPackage1", "desc");
+		impl.createCategory("", "testCreateNewRuleAsLinkCat1", "this is a cat");
+		impl.repository.createPackage("testCreateNewRuleAsLinkPackage2", "desc");
+		impl.createCategory("", "testCreateNewRuleAsLinkCat2", "this is a cat");
 
+		//Create the original asset.
+		String uuid = impl.createNewRule("testCreateLinkedAssetItemRule",
+				"an initial desc", "testCreateNewRuleAsLinkCat1", "testCreateNewRuleAsLinkPackage1",
+				AssetFormats.DSL_TEMPLATE_RULE);
+		assertNotNull(uuid);
+		assertFalse("".equals(uuid));
+
+		AssetItem dtItem = impl.repository.loadAssetByUUID(uuid);
+		assertEquals(dtItem.getDescription(), "an initial desc");
+		
+		//create an asset which is linked to an existing asset. Different package, same category.
+		String uuidLink = impl.createNewLinkedRule("testCreateLinkedAssetItemRuleLinked",
+				uuid, "testCreateNewRuleAsLinkCat1", "testCreateNewRuleAsLinkPackage2");
+		assertNotNull(uuidLink);
+		assertFalse("".equals(uuidLink));
+		assertFalse(uuidLink.equals(uuid));
+
+		//now verify the linked asset.
+		AssetItem itemLink = impl.repository.loadAssetByUUID(uuidLink);
+		assertEquals(itemLink.getName(), "testCreateLinkedAssetItemRuleLinked");
+		assertEquals(itemLink.getDescription(), "an initial desc");
+		assertEquals(itemLink.getFormat(), AssetFormats.DSL_TEMPLATE_RULE);
+		assertEquals(itemLink.getPackage().getName(), "testCreateNewRuleAsLinkPackage2");
+
+		assertEquals(itemLink.getPackageName(), "testCreateNewRuleAsLinkPackage2");
+		
+		assertTrue(itemLink.getCategories().size() == 1);
+		assertTrue(itemLink.getCategorySummary().contains("testCreateNewRuleAsLinkCat1"));
+		
+		//now verify the original asset.
+		AssetItem referredItem = impl.repository.loadAssetByUUID(uuid);
+		assertEquals(referredItem.getName(), "testCreateLinkedAssetItemRule");
+		assertEquals(referredItem.getDescription(), "an initial desc");
+		assertEquals(referredItem.getFormat(), AssetFormats.DSL_TEMPLATE_RULE);
+		assertEquals(referredItem.getPackage().getName(), "testCreateNewRuleAsLinkPackage1");
+
+		assertTrue(referredItem.getCategories().size() == 1);
+		assertTrue(referredItem.getCategorySummary().contains("testCreateNewRuleAsLinkCat1"));		
+
+		
+		//create an asset which refers to an existing asset. same package, different category.
+		String uuidLink1 = impl.createNewLinkedRule("testCreateLinkedAssetItemRuleLinked1",
+				uuid, "testCreateNewRuleAsLinkCat2", "testCreateNewRuleAsLinkPackage1");
+		assertNotNull(uuidLink1);
+		assertFalse("".equals(uuidLink1));
+		assertFalse(uuidLink1.equals(uuid));
+
+		
+		//now verify the linked asset.
+		AssetItem itemLink1 = impl.repository.loadAssetByUUID(uuidLink1);
+		assertEquals(itemLink1.getDescription(), "an initial desc");
+		assertEquals(itemLink1.getFormat(), AssetFormats.DSL_TEMPLATE_RULE);
+		assertEquals(itemLink1.getPackage().getName(), "testCreateNewRuleAsLinkPackage1");
+		assertEquals(itemLink1.getPackageName(), "testCreateNewRuleAsLinkPackage1");
+		
+		assertTrue(itemLink1.getCategories().size() == 2);
+		assertTrue(itemLink1.getCategorySummary().contains("testCreateNewRuleAsLinkCat1"));
+		assertTrue(itemLink1.getCategorySummary().contains("testCreateNewRuleAsLinkCat2"));
+		
+		//now verify the linked asset by calling PackageItem.loadAsset()
+		AssetItem itemLinkFromPackage1 = testCreateNewRuleAsLinkPackage1.loadAsset("testCreateLinkedAssetItemRuleLinked1");
+		assertEquals(itemLinkFromPackage1.getDescription(), "an initial desc");
+		assertEquals(itemLinkFromPackage1.getFormat(), AssetFormats.DSL_TEMPLATE_RULE);
+		assertEquals(itemLinkFromPackage1.getPackage().getName(), "testCreateNewRuleAsLinkPackage1");
+		assertEquals(itemLinkFromPackage1.getPackageName(), "testCreateNewRuleAsLinkPackage1");
+		
+		assertTrue(itemLinkFromPackage1.getCategories().size() == 2);
+		assertTrue(itemLinkFromPackage1.getCategorySummary().contains("testCreateNewRuleAsLinkCat1"));
+		assertTrue(itemLinkFromPackage1.getCategorySummary().contains("testCreateNewRuleAsLinkCat2"));
+		
+		//now verify the original asset.
+		AssetItem referredItem1 = impl.repository.loadAssetByUUID(uuid);
+		assertEquals(referredItem1.getDescription(), "an initial desc");
+		assertEquals(referredItem1.getFormat(), AssetFormats.DSL_TEMPLATE_RULE);
+		assertEquals(referredItem1.getPackage().getName(), "testCreateNewRuleAsLinkPackage1");
+		
+		assertTrue(referredItem1.getCategories().size() == 2);
+		assertTrue(referredItem1.getCategorySummary().contains("testCreateNewRuleAsLinkCat1"));		
+		assertTrue(referredItem1.getCategorySummary().contains("testCreateNewRuleAsLinkCat2"));
+		
+		//now verify AssetItemIterator works by calling search
+        AssetItemIterator it = impl.repository.findAssetsByName("testCreateLinkedAssetItemRule%",
+                true); 
+		assertEquals(3, it.getSize());
+		while(it.hasNext()) {
+			AssetItem ai = it.next();
+			if(ai.getUUID().equals(uuid)) {
+				assertEquals(ai.getPackage().getName(), "testCreateNewRuleAsLinkPackage1");
+				assertEquals(ai.getDescription(), "an initial desc");
+			} else if (ai.getUUID().equals(uuidLink)) {
+				assertEquals(ai.getPackage().getName(), "testCreateNewRuleAsLinkPackage2");
+				assertEquals(ai.getDescription(), "an initial desc");
+			} else if (ai.getUUID().equals(uuidLink1)) {
+				assertEquals(ai.getPackage().getName(), "testCreateNewRuleAsLinkPackage1");
+				assertEquals(ai.getDescription(), "an initial desc");
+			} else {
+				fail("unexptected asset found: " + ai.getPackage().getName());
+			}
+		}
 	}
+	
+	public void testLinkedAssetItemHistoryRelated() throws Exception {
+		ServiceImplementation impl = getService();
+		PackageItem testCreateNewRuleAsLinkPackage1 = impl.repository.createPackage("testLinkedAssetItemHistoryRelatedPack", "desc");
+		impl.createCategory("", "testLinkedAssetItemHistoryRelatedCat", "this is a cat");
 
+		//Create the original asset.
+		String uuid = impl.createNewRule("testLinkedAssetItemHistoryRelatedRule",
+				"an initial desc", "testLinkedAssetItemHistoryRelatedCat", "testLinkedAssetItemHistoryRelatedPack",
+				AssetFormats.DSL_TEMPLATE_RULE);
+		
+		//create an asset which refers to an existing asset.
+		String uuidLink = impl.createNewLinkedRule("testLinkedAssetItemHistoryRelatedRuleLinked",
+				uuid, "testLinkedAssetItemHistoryRelatedCat", "testLinkedAssetItemHistoryRelatedPack");
+		assertFalse(uuidLink.equals(uuid));
+
+		//create version 1.
+		RuleAsset assetWrapper = impl.loadRuleAsset(uuidLink);
+		assertEquals(assetWrapper.metaData.description, "an initial desc");
+		assetWrapper.metaData.description = "version 1";
+		String uuidLink1 = impl.checkinVersion(assetWrapper);
+		
+		//create version 2
+		RuleAsset assetWrapper2 = impl.loadRuleAsset(uuidLink);
+		assetWrapper2.metaData.description = "version 2";
+		String uuidLink2 = impl.checkinVersion(assetWrapper2);
+		
+		//create version head
+		RuleAsset assetWrapper3 = impl.loadRuleAsset(uuidLink);
+		assetWrapper3.metaData.description = "version head";
+		String uuidLink3 = impl.checkinVersion(assetWrapper3);
+
+		assertEquals(uuidLink, uuidLink1);
+		assertEquals(uuidLink, uuidLink2);
+
+		//verify the history info of LinkedAssetItem
+		TableDataResult result = impl.loadAssetHistory(uuidLink);
+		assertNotNull(result);
+		TableDataRow[] rows = result.data;
+		assertEquals(2, rows.length);
+		assertFalse(rows[0].id.equals(uuidLink));
+		assertFalse(rows[1].id.equals(uuidLink));
+
+		RuleAsset version1 = impl.loadRuleAsset(rows[0].id);
+		RuleAsset version2 = impl.loadRuleAsset(rows[1].id);
+		RuleAsset versionHead = impl.loadRuleAsset(uuidLink);
+		assertFalse(version1.metaData.versionNumber == version2.metaData.versionNumber);
+		assertFalse(version1.metaData.versionNumber == versionHead.metaData.versionNumber);
+		assertTrue(version1.metaData.description.equals("version 1"));
+		assertTrue(version2.metaData.description.equals("version 2"));
+		assertTrue(versionHead.metaData.description.equals("version head"));
+
+		//verify the history info of the original AssetItem
+		result = impl.loadAssetHistory(uuid);
+		assertNotNull(result);
+		rows = result.data;
+		assertEquals(2, rows.length);
+		assertFalse(rows[0].id.equals(uuid));
+		assertFalse(rows[1].id.equals(uuid));
+
+		version1 = impl.loadRuleAsset(rows[0].id);
+		version2 = impl.loadRuleAsset(rows[1].id);
+		versionHead = impl.loadRuleAsset(uuid);
+		assertFalse(version1.metaData.versionNumber == version2.metaData.versionNumber);
+		assertFalse(version1.metaData.versionNumber == versionHead.metaData.versionNumber);
+		assertTrue(version1.metaData.description.equals("version 1"));
+		assertTrue(version2.metaData.description.equals("version 2"));
+		assertTrue(versionHead.metaData.description.equals("version head"));
+
+		//test restore
+		impl.restoreVersion(version1.uuid, versionHead.uuid, "this was cause of a mistake");
+
+		RuleAsset newHead = impl.loadRuleAsset(uuid);
+
+		assertEquals("this was cause of a mistake",
+				newHead.metaData.checkinComment);
+	}
+
 	public void testCreateNewRuleContainsApostrophe() throws Exception {
 		ServiceImplementation impl = getService();
 		impl.repository.createPackage("testCreateNewRuleContainsApostrophe",
@@ -450,10 +635,6 @@
 				AssetFormats.DSL_TEMPLATE_RULE);
 		asset = impl.loadRuleAsset(uuid);
 		assertTrue(asset.content instanceof RuleContentText);
-
-
-		//asset
-
 	}
 
     public void testTrackRecentOpenedChanged() throws Exception {

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItemIterator.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItemIterator.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/AssetItemIterator.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -33,7 +33,7 @@
     }
 
     public AssetItem next() {
-        return new AssetItem( rulesRepository,
+        return new LinkedAssetItem( rulesRepository,
                              (Node) it.next() );
     }
 

Added: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/LinkedAssetItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/LinkedAssetItem.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/LinkedAssetItem.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -0,0 +1,202 @@
+package org.drools.repository;
+
+import java.io.*;
+import java.util.Calendar;
+import java.util.Iterator;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.UnsupportedRepositoryOperationException;
+
+import org.apache.log4j.Logger;
+import org.drools.repository.events.StorageEventManager;
+import org.drools.repository.utils.IOUtils;
+
+/**
+ * LinkedAssetItem does not represent a real Asset, instead it is a wrapper node that  
+ * wraps over an existing asset. LinkedAssetItem only has three properties that belongs to itself:
+ * NAME: LinkedAssetItem has its own name which is the node name
+ * LINKED_NODE_UUID: the node UUID that LinkedAssetItem links to.
+ * PACKAGE_NAME_PROPERTY: our current design only allows one AssetItem belongs to one package. 
+ * LinkedAssetItem and the linked(wrapped) asset have to have their own package name respectively. 
+ * NOTE: those three properties are read only. Thus there is no need for LinkedAssetItem to have its own
+ * check in/out method once it is created and saved.
+ * Requests to all other properties are delegated to the linked(wrapped) asset. 
+ */
+public class LinkedAssetItem extends AssetItem {
+    private Logger log = Logger.getLogger( LinkedAssetItem.class );
+ 
+    protected Node wrapperNode;
+    public static final String LINKED_NODE_UUID                = "drools:linkedNodeUUID";
+    
+    /**
+     * Constructs a LinkedAssetItem object, setting its node attribute to the specified node.
+     *
+     * @param rulesRepository the rulesRepository that instantiated this object
+     * @param node the node in the repository that this RuleItem corresponds to
+     * @throws RulesRepositoryException
+     */
+    public LinkedAssetItem(RulesRepository rulesRepository,
+                     Node wrapperNode) throws RulesRepositoryException {        
+        super( rulesRepository,	wrapperNode );
+        
+        try {
+			// If this node is a node that is linked to another node.
+			if (wrapperNode.hasProperty(LINKED_NODE_UUID)) {
+				Property linkedNodeUUIDProperty = wrapperNode
+						.getProperty(LINKED_NODE_UUID);
+				String linkedNodeUUID = linkedNodeUUIDProperty.getValue()
+						.getString();
+
+				Node linkedNode = rulesRepository.getSession().getNodeByUUID(
+						linkedNodeUUID);
+
+	        	this.wrapperNode = wrapperNode;  
+				this.node = linkedNode;
+				
+				//When a node is created, it is in checked out status. So we do similar to the linked node. 
+				if(!this.node.isCheckedOut()) {
+					this.node.checkout();
+				}
+			} else {
+				this.wrapperNode = null; 
+			}
+		} catch (RepositoryException e) {
+			this.wrapperNode = null; 
+		}      
+    }
+
+    public LinkedAssetItem() {
+        super( null,
+               null );
+    }
+    
+    /**
+     * @return A unique identifier for this items content node.
+     * return the UUID of the wrapper node. 
+     */
+    public String getUUID() {
+		if (wrapperNode == null) {
+			return super.getUUID();
+		} else {
+	        try {
+	            return this.getVersionContentNode1().getUUID();
+	        } catch (  RepositoryException e ) {
+	            throw new RulesRepositoryException(e);
+	        }
+		}
+    }
+    
+    /**
+     * Need to get the name from the content node, not the version node
+     * if it is in fact a version !
+     */
+    public String getName() {
+		if (wrapperNode == null) {
+			return super.getName();
+		} else {
+	        try {
+	            return this.getVersionContentNode1().getName();
+	        } catch (  RepositoryException e ) {
+	            throw new RulesRepositoryException(e);
+	        }
+		}
+    }
+
+    /**
+     * This will get the package that the wrapper asset belongs to.
+     */
+    public PackageItem getPackage() {
+		if (wrapperNode == null) {
+			return super.getPackage();
+		} else {
+	        try {
+	            if ( this.isHistoricalVersion() ) {
+	            	return this.rulesRepository.loadPackage(this.getPackageName());
+	            }
+	            return new PackageItem( this.rulesRepository,
+	                                    this.wrapperNode.getParent().getParent() );
+	        } catch ( RepositoryException e ) {
+	            throw new RulesRepositoryException( e );
+	        }
+		}
+
+    }
+    
+    /**
+     * Get the wrapper asset's package name.
+     */
+    public String getPackageName() {
+		if (wrapperNode == null) {
+			return super.getPackageName();
+		} else {
+			return getStringProperty1(PACKAGE_NAME_PROPERTY);
+		}
+	}      
+  
+     /**
+     * This will save the content (if it hasn't been already) and
+     * then check it in to create a new version.
+     * It will also set the last modified property.
+     */
+    public void checkin(String comment) {
+    	super.checkin(comment);
+    	
+    	//LinkedAssetItem only has read-only properties. So actually save and checkin is only needed once
+    	//when LinkedAssetItem is created. 
+		if (wrapperNode != null) {
+            checkIsUpdateable1();
+			try {
+				this.wrapperNode.getSession().save();
+				this.wrapperNode.checkin();
+
+				if (StorageEventManager.hasSaveEvent()) {
+					if (this instanceof AssetItem) {
+						StorageEventManager.getSaveEvent().onAssetCheckin(
+								(AssetItem) this);
+					}
+				}
+				StorageEventManager.doCheckinEvents(this);
+
+			} catch (RepositoryException e) {
+				throw new RulesRepositoryException("Unable to checkin.", e);
+			}
+		}
+    }
+    
+    public String getStringProperty1(String property) {
+        try {
+            Node theNode = getVersionContentNode1();
+            if ( theNode.hasProperty( property ) ) {
+                Property data = theNode.getProperty( property );
+                return data.getValue().getString();
+            } else {
+                return "";
+            }
+        } catch ( RepositoryException e ) {
+            throw new RulesRepositoryException( e );
+        }
+    }
+    
+    public Node getVersionContentNode1() throws RepositoryException,
+                                       PathNotFoundException {
+        return getRealContentFromVersion(this.wrapperNode);
+    }
+    
+    protected void checkIsUpdateable1() {
+        try {
+            if ( this.wrapperNode.getPrimaryNodeType().getName().equals( "nt:version" ) ) {
+                String message = "Error. Tags can only be added to the head version of a rule node";
+                log.error( message );
+                throw new RulesRepositoryException( message );
+            }
+        } catch ( RepositoryException e ) {
+            throw new RulesRepositoryException( e );
+        }
+    }
+
+ }
\ No newline at end of file


Property changes on: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/LinkedAssetItem.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/PackageItem.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -225,8 +225,81 @@
 
     }
 
+    /**
+     * This adds a rule which is linked to an existing rule. 
+     *
+     * This will NOT check the asset in, just create the basic record.
+     * @param assetName The name of the asset (the file name minus the extension)
+     * @param linkedAssetUUID the UUID of the existing rule that this asset is linked to.
+     */
+    public AssetItem addLinkedAsset(String assetName, String linkedAssetUUID) {
+    	return addLinkedAsset(assetName, linkedAssetUUID, null);    	
+    }
+    /**
+     * This adds a rule which is linked to an existing rule. 
+     *
+     * This will NOT check the asset in, just create the basic record.
+     * @param assetName The name of the asset (the file name minus the extension)
+     * @param linkedAssetUUID the UUID of the existing rule that this asset is linked to.
+     * @param initialCategory The initial category the asset is placed in (can belong to multiple ones later).
+     */
+    public AssetItem addLinkedAsset(String assetName, String linkedAssetUUID,
+                            String initialCategory) {
+        Node wrapperNode;
+        try {
+        	assetName = assetName.trim();
+            Node rulesFolder = this.node.getNode( ASSET_FOLDER_NAME );
+            wrapperNode = rulesFolder.addNode( assetName,
+                                            AssetItem.RULE_NODE_TYPE_NAME );
+            wrapperNode.setProperty( AssetItem.TITLE_PROPERTY_NAME,
+                                  assetName );
 
+            wrapperNode.setProperty( AssetItem.DESCRIPTION_PROPERTY_NAME,
+                                  "description_IGNORED" );
+            /*
+            if (format != null) {
+                ruleNode.setProperty( AssetItem.FORMAT_PROPERTY_NAME,
+                                      format );
+            } else {
+                ruleNode.setProperty( AssetItem.FORMAT_PROPERTY_NAME,
+                                      AssetItem.DEFAULT_CONTENT_FORMAT );
+            }
 
+
+            ruleNode.setProperty( VersionableItem.CHECKIN_COMMENT,
+                                  "Initial" );
+*/
+            Calendar lastModified = Calendar.getInstance();
+            wrapperNode.setProperty( AssetItem.LAST_MODIFIED_PROPERTY_NAME, lastModified );
+            wrapperNode.setProperty( AssetItem.PACKAGE_NAME_PROPERTY, this.getName() );
+            wrapperNode.setProperty( AssetItem.FORMAT_PROPERTY_NAME,
+                    AssetItem.DEFAULT_CONTENT_FORMAT );
+
+            //ruleNode.setProperty( CREATOR_PROPERTY_NAME, this.node.getSession().getUserID() );
+
+            wrapperNode.setProperty( LinkedAssetItem.LINKED_NODE_UUID, linkedAssetUUID );
+
+            AssetItem rule = new LinkedAssetItem( this.rulesRepository, wrapperNode );
+
+            //rule.updateState( StateItem.DRAFT_STATE_NAME );
+
+            if (initialCategory != null) {
+                rule.addCategory( initialCategory );
+            }
+
+            return rule;
+
+        } catch ( RepositoryException e ) {
+            if ( e instanceof ItemExistsException ) {
+                throw new RulesRepositoryException( "A rule of that name already exists in that package.",
+                                                    e );
+            } else {
+                throw new RulesRepositoryException( e );
+            }
+        }
+
+    }
+
     /**
      * This will permanently delete this package.
      */
@@ -499,7 +572,7 @@
 
         try {
             Node content = getVersionContentNode();
-            return new AssetItem(
+            return new LinkedAssetItem(
                         this.rulesRepository,
                         content.getNode( ASSET_FOLDER_NAME ).getNode( name ));
         } catch ( RepositoryException e ) {

Modified: labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-repository/src/main/java/org/drools/repository/RulesRepository.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -619,7 +619,7 @@
     public AssetItem loadAssetByUUID(String uuid) {
         try {
             Node rulePackageNode = this.session.getNodeByUUID( uuid );
-            return new AssetItem( this,
+            return new LinkedAssetItem( this,
                                   rulePackageNode );
         } catch (ItemNotFoundException e) {
           log.warn(e);
@@ -642,7 +642,7 @@
      *            what description to use for the node
      * @return a PackageItem, encapsulating the created node
      * @throws RulesRepositoryException
-     */
+     */	
     public PackageItem createPackage(String name,
                                      String description) throws RulesRepositoryException {
         Node folderNode = this.getAreaNode( RULE_PACKAGE_AREA );

Added: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/LinkedAssetItemTest.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/LinkedAssetItemTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/LinkedAssetItemTest.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -0,0 +1,985 @@
+package org.drools.repository;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionIterator;
+
+import junit.framework.TestCase;
+import org.drools.repository.events.StorageEventManager;
+
+public class LinkedAssetItemTest extends TestCase {
+
+	private RulesRepository getRepo() {
+		return RepositorySessionUtil.getRepository();
+	}
+
+	private PackageItem getDefaultPackage() {
+		return getRepo().loadDefaultPackage();
+	}
+
+	public void testAssetItemCreation() throws Exception {
+
+		Calendar now = Calendar.getInstance();
+
+		Thread.sleep(500); // MN: need this sleep to get the correct date
+
+		AssetItem ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestRuleItem",
+				"test content");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestRuleItem", ruleItem1.getUUID(), null);
+
+		assertNotNull(linkedRuleItem1);
+		assertNotNull(linkedRuleItem1.getNode());
+		assertEquals("LinkedAssetItemlinkedTestRuleItem", linkedRuleItem1.getName());
+		assertEquals("LinkedAssetItemtestRuleItem", ruleItem1.getName());
+
+		assertNotNull(ruleItem1.getCreatedDate());
+		assertNotNull(linkedRuleItem1.getCreatedDate());
+
+		assertTrue(now.before(ruleItem1.getCreatedDate()));
+		assertTrue(now.before(linkedRuleItem1.getCreatedDate()));
+
+		String packName = getDefaultPackage().getName();
+
+		assertEquals(packName, ruleItem1.getPackageName());
+		assertEquals(packName, linkedRuleItem1.getPackageName());
+
+		assertNotNull(ruleItem1.getUUID());
+		assertNotNull(linkedRuleItem1.getUUID());
+		assertTrue(linkedRuleItem1.getUUID() != linkedRuleItem1.getUUID());
+
+		// try constructing with node of wrong type
+		try {
+
+			PackageItem pitem = getRepo().loadDefaultPackage();
+			new AssetItem(getRepo(), pitem.getNode());
+			fail("Exception not thrown for node of wrong type");
+		} catch (RulesRepositoryException e) {
+			assertNotNull(e.getMessage());
+		} catch (Exception e) {
+			fail("Caught unexpected exception: " + e);
+		}
+
+		// try constructing with node of wrong type
+		try {
+
+			PackageItem pitem = getRepo().loadDefaultPackage();
+			new LinkedAssetItem(getRepo(), pitem.getNode());
+			fail("Exception not thrown for node of wrong type");
+		} catch (RulesRepositoryException e) {
+			assertNotNull(e.getMessage());
+		} catch (Exception e) {
+			fail("Caught unexpected exception: " + e);
+		}
+	}
+
+	public void testGetContentLength() throws Exception {
+		RulesRepository repo = getRepo();
+		PackageItem pkg = repo.loadDefaultPackage();
+		AssetItem asset = pkg.addAsset("LinkedAssetItemtestGetContentLength", "");
+		AssetItem linkedAsset = pkg.addLinkedAsset("LinkedAssetItemlinkedTestGetContentLength", asset.getUUID(), null);
+		
+		assertEquals(0, asset.getContentLength());
+		assertEquals(0, linkedAsset.getContentLength());
+		asset.updateContent("boo");
+		asset.checkin("");
+		assertEquals("boo".getBytes().length, asset.getContentLength());
+		assertEquals("boo".getBytes().length, linkedAsset.getContentLength());
+		
+		asset = pkg.addAsset("LinkedAssetItemtestGetContentLength2", "");
+		linkedAsset = pkg.addLinkedAsset("LinkedAssetItemlinkedTestGetContentLength2", asset.getUUID(), null);
+
+		assertEquals(0, asset.getContentLength());
+		linkedAsset.updateBinaryContentAttachment(new ByteArrayInputStream("foobar"
+				.getBytes()));
+		linkedAsset.checkin("");
+		assertEquals("foobar".getBytes().length, asset.getContentLength());
+		assertEquals("foobar".getBytes().length, linkedAsset.getContentLength());
+	}
+
+	public void testGetPackageItem() throws Exception {
+		RulesRepository repo = getRepo();
+		PackageItem def = repo.loadDefaultPackage();
+		AssetItem asset = repo.loadDefaultPackage().addAsset("LinkedAssetItemtestPackageItem",
+				"test content");
+		AssetItem linkedAsset = repo.loadDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestPackageItem",asset.getUUID(), null);
+
+		PackageItem pkg = asset.getPackage();
+		assertEquals(def.getName(), pkg.getName());
+		assertEquals(def.getUUID(), pkg.getUUID());
+		
+		PackageItem linkedPkg = linkedAsset.getPackage();
+		assertEquals(def.getName(), linkedPkg.getName());
+		assertEquals(def.getUUID(), linkedPkg.getUUID());
+	}
+
+	public void testUpdateStringProperty() throws Exception {
+		RulesRepository repo = getRepo();
+		AssetItem asset = repo.loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestUpdateStringProperty", "test content");
+		AssetItem linkedAsset = repo.loadDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestUpdateStringProperty",asset.getUUID(), null);		
+		linkedAsset.updateContent("new content");
+		linkedAsset.checkin("");
+		Calendar lm = linkedAsset.getLastModified();
+
+		Thread.sleep(100);
+		linkedAsset.updateStringProperty("Anything", "AField");
+
+		assertEquals("Anything", linkedAsset.getStringProperty("AField"));
+		assertEquals("Anything", asset.getStringProperty("AField"));
+		
+		Calendar lm1 = asset.getLastModified();
+		assertTrue(lm1.getTimeInMillis() > lm.getTimeInMillis());
+		Calendar lm2 = asset.getLastModified();
+		assertTrue(lm2.getTimeInMillis() > lm.getTimeInMillis());
+		
+		Thread.sleep(100);
+
+		asset.updateStringProperty("More", "AField", false);
+
+		assertEquals(lm1.getTimeInMillis(), asset.getLastModified()
+				.getTimeInMillis());
+		assertEquals(lm2.getTimeInMillis(), linkedAsset.getLastModified()
+				.getTimeInMillis());
+		
+		asset.updateContent("more content");
+		asset.checkin("");
+
+		asset = repo.loadAssetByUUID(asset.getUUID());
+		assertEquals("More", asset.getStringProperty("AField"));
+		assertEquals("more content", asset.getContent());		
+		linkedAsset = repo.loadAssetByUUID(linkedAsset.getUUID());
+		assertEquals("More", linkedAsset.getStringProperty("AField"));
+		assertEquals("more content", asset.getContent());
+	}
+
+	public void testGetPackageItemHistorical() throws Exception {
+		RulesRepository repo = getRepo();
+		PackageItem pkg = repo
+				.createPackage("LinkedAssetItemtestGetPackageItemHistorical", "");
+		AssetItem asset = pkg.addAsset("LinkedAssetItemwhee", "");
+		
+		//Version 1, created by the original asset
+		asset.checkin("");
+		assertNotNull(asset.getPackage());
+
+		AssetItem linkedAsset = pkg.addLinkedAsset("LinkedAssetItemlinkedWhee", asset.getUUID(), null);
+		
+		//Version 2, created by LinkedAssetItem
+		linkedAsset.checkin("");
+		
+		repo.createPackageSnapshot(pkg.getName(), "SNAP");
+
+		PackageItem pkg_ = repo.loadPackageSnapshot(pkg.getName(), "SNAP");
+		AssetItem asset_ = pkg_.loadAsset("LinkedAssetItemwhee");
+		PackageItem pkg__ = asset_.getPackage();
+		assertTrue(pkg__.isSnapshot());
+		assertTrue(pkg_.isSnapshot());
+		assertFalse(pkg.isSnapshot());
+		assertEquals(pkg.getName(), pkg__.getName());
+		
+		AssetItem linkedAsset_ = pkg_.loadAsset("LinkedAssetItemlinkedWhee");
+		PackageItem linkedPkg__ = linkedAsset_.getPackage();
+		assertTrue(linkedPkg__.isSnapshot());
+		assertFalse(pkg.isSnapshot());
+		assertEquals(pkg.getName(), linkedPkg__.getName());
+		
+		linkedAsset.updateDescription("yeah !");
+		
+		//Version 3, created by LinkedAssetItem
+		linkedAsset.checkin("new");
+
+		linkedAsset = pkg.loadAsset("LinkedAssetItemlinkedWhee");
+		assertNotNull(linkedAsset.getPackage());
+
+		AssetHistoryIterator linkedIt = linkedAsset.getHistory();
+		assertEquals(4, iteratorToList(linkedIt).size());		
+		
+		asset = pkg.loadAsset("LinkedAssetItemwhee");
+		AssetHistoryIterator it = asset.getHistory();
+		assertEquals(4, iteratorToList(it).size());		
+	}
+	
+    List iteratorToList(Iterator it) {
+        List list = new ArrayList();
+        while(it.hasNext()) {
+            list.add( it.next() );
+        }
+        return list;
+    }
+
+	public void testGetContent() {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetContent", "test content");
+		AssetItem linkedRuleItem1 = getRepo().loadDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestGetContent", ruleItem1.getUUID(), null);
+		
+		linkedRuleItem1.updateContent("test content");
+		linkedRuleItem1.updateFormat("drl");
+
+		assertNotNull(linkedRuleItem1.getNode());
+		assertEquals("test content", linkedRuleItem1.getContent());
+		assertEquals("test content", ruleItem1.getContent());
+
+		assertFalse(linkedRuleItem1.isBinary());
+		assertFalse(ruleItem1.isBinary());
+
+		assertNotNull(linkedRuleItem1.getBinaryContentAsBytes());
+		assertNotNull(linkedRuleItem1.getBinaryContentAttachment());
+		String content = new String(linkedRuleItem1.getBinaryContentAsBytes());
+		assertNotNull(content);
+		content = new String(ruleItem1.getBinaryContentAsBytes());
+		assertNotNull(content);	
+	}
+
+	public void testUpdateContent() throws Exception {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestUpdateContent",
+				"test description");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestUpdateContent",
+				ruleItem1.getUUID(), null);
+
+		assertFalse(ruleItem1.getCreator().equals(""));
+		assertFalse(linkedRuleItem1.getCreator().equals(""));
+		linkedRuleItem1.updateContent("test content");
+		linkedRuleItem1.checkin("yeah");
+
+		assertFalse(linkedRuleItem1.getLastContributor().equals(""));
+		assertFalse(ruleItem1.getLastContributor().equals(""));
+
+		linkedRuleItem1.updateContent("new rule content");
+
+		assertEquals("new rule content", linkedRuleItem1.getContent());
+
+		assertTrue(linkedRuleItem1.getNode().getSession().hasPendingChanges());
+		assertTrue(ruleItem1.getNode().getSession().hasPendingChanges());
+
+		ruleItem1.checkin("yeah !");
+		assertFalse(ruleItem1.getNode().getSession().hasPendingChanges());
+		assertEquals("yeah !", ruleItem1.getCheckinComment());
+		
+		try {
+		    linkedRuleItem1.checkin("yeah linked !");
+		    fail("Did not get expected exception: Unable to checkin");
+		} catch (RulesRepositoryException e) {
+			
+		}
+
+		AssetItem prev = (AssetItem) ruleItem1.getPrecedingVersion();
+		assertEquals("test content", prev.getContent());
+		assertFalse("yeah !".equals(prev.getCheckinComment()));
+
+		ruleItem1 = getDefaultPackage().loadAsset("LinkedAssetItemtestUpdateContent");
+		VersionIterator it = ruleItem1.getNode().getVersionHistory()
+				.getAllVersions();
+
+		// and this shows using a version iterator.
+		// perhaps migrate to using this rather then next/prev methods.
+		// this way, we can skip.
+		assertTrue(it.hasNext());
+		while (it.hasNext()) {
+			Version n = it.nextVersion();
+			AssetItem item = new AssetItem(ruleItem1.getRulesRepository(), n);
+			assertNotNull(item);
+		}
+	}
+
+	public void testCategoriesPagination() {
+		PackageItem pkg = getRepo().createPackage("LinkedAssetItemtestPagination", "");
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestPagedTag", "description");
+
+		AssetItem a = pkg.addAsset("LinkedAssetItemtestPage1", "test content");
+		a.addCategory("LinkedAssetItemtestPagedTag");
+		a.checkin("");
+		
+		a = pkg.addLinkedAsset("LinkedAssetItemlinkedTestPage1", a.getUUID(), null);
+		a.addCategory("LinkedAssetItemtestPagedTag");
+		a.checkin("");		
+		
+		a = pkg.addAsset("LinkedAssetItemtestPage2", "test content");
+		a.addCategory("LinkedAssetItemtestPagedTag");
+		a.checkin("");
+
+
+		a = pkg.addAsset("LinkedAssetItemtestPage3", "test content");
+		a.addCategory("LinkedAssetItemtestPagedTag");
+		a.checkin("");
+
+		a = pkg.addAsset("LinkedAssetItemtestPage4", "test content");
+		a.addCategory("LinkedAssetItemtestPagedTag");
+		a.checkin("");
+
+		a = pkg.addAsset("LinkedAssetItemtestPage5", "test content");
+		a.addCategory("LinkedAssetItemtestPagedTag");
+		a.checkin("");
+
+		AssetPageList list = getRepo().findAssetsByCategory("LinkedAssetItemtestPagedTag", 0,
+				-1);
+		assertTrue(list.currentPosition > 0);
+		assertEquals(5, list.assets.size());
+		assertEquals(false, list.hasNext);
+
+		list = getRepo().findAssetsByCategory("LinkedAssetItemtestPagedTag", 0, 2);
+		assertTrue(list.currentPosition > 0);
+		assertEquals(true, list.hasNext);
+		assertEquals(2, list.assets.size());
+
+		assertEquals("LinkedAssetItemtestPage1", ((AssetItem) list.assets.get(0)).getName());
+		assertEquals("LinkedAssetItemtestPage2", ((AssetItem) list.assets.get(1)).getName());
+
+		list = getRepo().findAssetsByCategory("LinkedAssetItemtestPagedTag", 2, 2);
+		assertTrue(list.currentPosition > 0);
+		assertEquals(true, list.hasNext);
+		assertEquals(2, list.assets.size());
+
+		assertEquals("LinkedAssetItemtestPage3", ((AssetItem) list.assets.get(0)).getName());
+		assertEquals("LinkedAssetItemtestPage4", ((AssetItem) list.assets.get(1)).getName());
+
+		list = getRepo().findAssetsByCategory("LinkedAssetItemtestPagedTag", 2, 3);
+		assertTrue(list.currentPosition > 0);
+		assertEquals(false, list.hasNext);
+		assertEquals(3, list.assets.size());
+
+		assertEquals("LinkedAssetItemtestPage3", ((AssetItem) list.assets.get(0)).getName());
+		assertEquals("LinkedAssetItemtestPage4", ((AssetItem) list.assets.get(1)).getName());
+		assertEquals("LinkedAssetItemtestPage5", ((AssetItem) list.assets.get(2)).getName());
+	}
+
+	public void testCategories() {
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestAddTagTestTag",
+				"description");
+		AssetItem ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestAddTag",
+				"test content");	
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestAddTag", ruleItem1.getUUID(), null);
+
+		linkedRuleItem1.addCategory("LinkedAssetItemtestAddTagTestTag");
+		List tags = linkedRuleItem1.getCategories();
+		assertEquals(1, tags.size());
+		assertEquals("LinkedAssetItemtestAddTagTestTag", ((CategoryItem) tags.get(0))
+				.getName());
+
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestAddTagTestTag2",
+				"description");
+		linkedRuleItem1.addCategory("LinkedAssetItemtestAddTagTestTag2");
+		tags = linkedRuleItem1.getCategories();
+		assertEquals(2, tags.size());
+
+		linkedRuleItem1.checkin("woot");
+
+		// now test retrieve by tags
+		List result = getRepo()
+				.findAssetsByCategory("LinkedAssetItemtestAddTagTestTag", 0, -1).assets;
+		assertEquals(1, result.size());
+		AssetItem retItem = (AssetItem) result.get(0);
+		assertEquals("LinkedAssetItemtestAddTag", retItem.getName());
+
+		ruleItem1.updateContent("foo");
+		ruleItem1.checkin("latest");
+
+		assertTrue(ruleItem1.getCategories().size() > 0);
+		assertNotNull(ruleItem1.getCategorySummary());
+		assertEquals("LinkedAssetItemtestAddTagTestTag LinkedAssetItemtestAddTagTestTag2 ", ruleItem1
+				.getCategorySummary());
+
+		//REVISIT: findAssetsByCategory wont return a LinkedAssetItem
+		result = getRepo().findAssetsByCategory("LinkedAssetItemtestAddTagTestTag", 0, -1).assets;
+
+		assertEquals(1, result.size());
+
+		ruleItem1 = (AssetItem) result.get(0);
+		assertEquals(2, ruleItem1.getCategories().size());
+
+		assertEquals("foo", ruleItem1.getContent());
+		AssetItem prev = (AssetItem) ruleItem1.getPrecedingVersion();
+		assertNotNull(prev);
+	}
+
+	public void testUpdateCategories() {
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestUpdateCategoriesOnAsset",
+				"la");
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestUpdateCategoriesOnAsset2",
+				"la");
+
+		AssetItem item = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestUpdateCategoriesOnAsset", "huhuhu");
+		AssetItem linkedItem = getRepo().loadDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestUpdateCategoriesOnAsset",
+				item.getUUID(), null);
+		
+		String[] cats = new String[] { "LinkedAssetItemtestUpdateCategoriesOnAsset",
+				"LinkedAssetItemtestUpdateCategoriesOnAsset2" };
+		linkedItem.updateCategoryList(cats);
+
+		linkedItem.checkin("aaa");
+
+		item = getRepo().loadDefaultPackage().loadAsset(
+				"LinkedAssetItemlinkedTestUpdateCategoriesOnAsset");
+		assertEquals(2, item.getCategories().size());
+
+		for (Iterator iter = item.getCategories().iterator(); iter.hasNext();) {
+			CategoryItem cat = (CategoryItem) iter.next();
+			assertTrue(cat.getName().startsWith("LinkedAssetItemtestUpdateCategoriesOnAsset"));
+		}
+	}
+
+	public void testFindRulesByCategory() throws Exception {
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestFindRulesByCat", "yeah");
+		AssetItem as1 = getDefaultPackage().addAsset(
+				"LinkedAssetItemtestFindRulesByCategory1", "ya", "LinkedAssetItemtestFindRulesByCat", "drl");
+		getDefaultPackage().addAsset("LinkedAssetItemtestFindRulesByCategory2", "ya",
+				"LinkedAssetItemtestFindRulesByCat", AssetItem.DEFAULT_CONTENT_FORMAT)
+				.checkin("version0");
+
+		as1.checkin("version0");
+		
+		AssetItem linkedItem = getRepo().loadDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestFindRulesByCategory1",
+				as1.getUUID(), "LinkedAssetItemtestFindRulesByCat");
+
+		//REVISIT: findAssetsByCategory wont return a LinkedAssetItem
+		List rules = getRepo()
+				.findAssetsByCategory("LinkedAssetItemtestFindRulesByCat", 0, -1).assets;
+		assertEquals(2, rules.size());
+
+		for (Iterator iter = rules.iterator(); iter.hasNext();) {
+			AssetItem element = (AssetItem) iter.next();
+			assertTrue(element.getName().startsWith("LinkedAssetItemtestFindRulesByCategory"));
+		}
+		
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemtestFindRulesByCat1", "yeah");
+		AssetItem linkedItem1 = getRepo().loadDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestFindRulesByCategory2",
+				as1.getUUID(), "LinkedAssetItemtestFindRulesByCat1");
+		linkedItem1.checkin("version2");
+		rules = getRepo().findAssetsByCategory("LinkedAssetItemtestFindRulesByCat1", 0, -1).assets;
+        assertEquals(1, rules.size());
+
+		try {
+			getRepo().loadCategory("LinkedAssetItemtestFindRulesByCat").remove();
+			fail("should not be able to remove");
+		} catch (RulesRepositoryException e) {
+			// assertTrue(e.getCause() instanceof
+			// ReferentialIntegrityException);
+			assertNotNull(e.getMessage());
+		}
+	}
+
+	public void testRemoveTag() {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestRemoveTag",
+				"test content");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset("LinkedAssetItemlinkedTestRemoveTag",
+				ruleItem1.getUUID(), null);
+
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemTestRemoveCategory",
+				"description");
+
+		linkedRuleItem1.addCategory("LinkedAssetItemTestRemoveCategory");
+		List tags = linkedRuleItem1.getCategories();
+		assertEquals(1, tags.size());
+		linkedRuleItem1.removeCategory("LinkedAssetItemTestRemoveCategory");
+		tags = linkedRuleItem1.getCategories();
+		assertEquals(0, tags.size());
+
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemTestRemoveCategory2",
+				"description");
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemTestRemoveCategory3",
+				"description");
+		linkedRuleItem1.addCategory("LinkedAssetItemTestRemoveCategory2");
+		linkedRuleItem1.addCategory("LinkedAssetItemTestRemoveCategory3");
+		linkedRuleItem1.removeCategory("LinkedAssetItemTestRemoveCategory2");
+		tags = linkedRuleItem1.getCategories();
+		assertEquals(1, tags.size());
+		assertEquals("LinkedAssetItemTestRemoveCategory3", ((CategoryItem) tags.get(0))
+				.getName());
+	}
+
+	public void testSetStateString() {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset(
+				"LinkedAssetItemtestSetStateString", "test content");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestSetStateString", ruleItem1.getUUID());
+
+		getRepo().createState("TestState1");
+
+		linkedRuleItem1.updateState("TestState1");
+		assertNotNull(linkedRuleItem1.getState());
+		assertEquals("TestState1", linkedRuleItem1.getState().getName());
+
+		getRepo().createState("TestState2");
+		linkedRuleItem1.updateState("TestState2");
+		assertNotNull(linkedRuleItem1.getState());
+		assertEquals("TestState2", linkedRuleItem1.getState().getName());
+	}
+
+	public void testStatusStuff() {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestGetState",
+				"test content");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestGetState", ruleItem1.getUUID());
+		
+		StateItem stateItem1 = linkedRuleItem1.getState();
+		assertEquals(StateItem.DRAFT_STATE_NAME, stateItem1.getName());
+
+		linkedRuleItem1.updateState("TestState1");
+		assertNotNull(linkedRuleItem1.getState());
+		assertEquals("TestState1", linkedRuleItem1.getState().getName());
+
+		ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestGetState2", "wa");
+		linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestGetState2", ruleItem1.getUUID());
+		assertEquals(StateItem.DRAFT_STATE_NAME, linkedRuleItem1
+				.getStateDescription());
+		assertEquals(getRepo().getState(StateItem.DRAFT_STATE_NAME), linkedRuleItem1
+				.getState());
+	}
+
+	public void testToString() {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset("LinkedAssetItemtestToString",
+				"test content");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestToString", ruleItem1.getUUID());
+		assertNotNull(linkedRuleItem1.toString());
+	}
+
+	public void testGetLastModifiedOnCheckin() throws Exception {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetLastModified", "test content");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedTestGetLastModified", ruleItem1.getUUID());
+		
+		Calendar cal = Calendar.getInstance();
+		long before = cal.getTimeInMillis();
+
+		Thread.sleep(100);
+		linkedRuleItem1.updateContent("new lhs");
+		linkedRuleItem1.checkin("woot");
+		Calendar cal2 = linkedRuleItem1.getLastModified();
+		long lastMod = cal2.getTimeInMillis();
+
+		cal = Calendar.getInstance();
+		long after = cal.getTimeInMillis();
+
+		assertTrue(before < lastMod);
+		assertTrue(lastMod < after);
+	}
+
+	public void testGetDateEffective() {
+		AssetItem ruleItem1 = getDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetDateEffective", "test content");
+
+		// it should be initialized to null
+		assertTrue(ruleItem1.getDateEffective() == null);
+
+		// now try setting it, then retrieving it
+		Calendar cal = Calendar.getInstance();
+		ruleItem1.updateDateEffective(cal);
+		Calendar cal2 = ruleItem1.getDateEffective();
+
+		assertEquals(cal, cal2);
+	}
+
+	public void testGetDateExpired() {
+		try {
+			AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+					"LinkedAssetItemtestGetDateExpired", "test content");
+			AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+					"LinkedAssetItemlinkedtestGetDateExpired", ruleItem1.getUUID());
+			
+			// it should be initialized to null
+			assertTrue(linkedRuleItem1.getDateExpired() == null);
+
+			// now try setting it, then retrieving it
+			Calendar cal = Calendar.getInstance();
+			linkedRuleItem1.updateDateExpired(cal);
+			Calendar cal2 = linkedRuleItem1.getDateExpired();
+
+			assertEquals(cal, cal2);
+		} catch (Exception e) {
+			fail("Caught unexpected exception: " + e);
+		}
+	}
+
+	public void testSaveAndCheckinDescriptionAndTitle() throws Exception {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetDescription", "");
+		ruleItem1.checkin("version0");
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestGetDescription", ruleItem1.getUUID());
+		//This check in has no effect on ruleItem1, as nothing related to ruleItem1 has been changed
+		linkedRuleItem1.checkin("version1");		
+
+		// it should be "" to begin with
+		assertEquals("", linkedRuleItem1.getDescription());
+
+		linkedRuleItem1.updateDescription("test description");
+		assertEquals("test description", linkedRuleItem1.getDescription());
+
+		assertTrue(getRepo().getSession().hasPendingChanges());
+
+		linkedRuleItem1.updateTitle("This is a title");
+		assertTrue(getRepo().getSession().hasPendingChanges());
+		linkedRuleItem1.checkin("ya");
+
+		// we can save without a checkin
+		getRepo().getSession().save();
+
+		assertFalse(getRepo().getSession().hasPendingChanges());
+
+		try {
+			linkedRuleItem1.getPrecedingVersion().updateTitle("baaad");
+			fail("should not be able to do this");
+		} catch (RulesRepositoryException e) {
+			assertNotNull(e.getMessage());
+		}
+	}
+
+	public void testGetPrecedingVersionAndRestore() throws Exception {
+		getRepo().loadCategory("/").addCategory("LinkedAssetItemfoo", "ka");
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetPrecedingVersion", "descr");
+		ruleItem1.checkin("version0");
+		assertTrue(ruleItem1.getPrecedingVersion() == null);
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestGetPrecedingVersion", ruleItem1.getUUID());
+		linkedRuleItem1.checkin("version0");		
+		assertNotNull(ruleItem1.getPrecedingVersion());
+		assertNotNull(linkedRuleItem1.getPrecedingVersion());
+
+		linkedRuleItem1.addCategory("LinkedAssetItemfoo");
+		linkedRuleItem1.updateContent("test content");
+		linkedRuleItem1.updateDescription("descr2");
+		Thread.sleep(100);
+		linkedRuleItem1.checkin("boo");
+
+		AssetItem predecessorRuleItem = (AssetItem) linkedRuleItem1
+				.getPrecedingVersion();
+		assertNotNull(predecessorRuleItem);
+
+		// check version handling
+		assertNotNull(predecessorRuleItem.getVersionSnapshotUUID());
+		assertFalse(predecessorRuleItem.getVersionSnapshotUUID().equals(
+				ruleItem1.getUUID()));
+
+		// assertEquals(predecessorRuleItem.getCreatedDate().getTimeInMillis(),
+		// ruleItem1.getCreatedDate().getTimeInMillis());
+
+		assertEquals(ruleItem1.getState().getName(), predecessorRuleItem
+				.getState().getName());
+		// assertEquals(ruleItem1.getName(), predecessorRuleItem.getName());
+
+		AssetItem loadedHistorical = getRepo().loadAssetByUUID(
+				predecessorRuleItem.getVersionSnapshotUUID());
+		assertTrue(loadedHistorical.isHistoricalVersion());
+		assertFalse(ruleItem1.getVersionNumber() == loadedHistorical
+				.getVersionNumber());
+
+		linkedRuleItem1.updateContent("new content");
+		linkedRuleItem1.checkin("two changes");
+
+		predecessorRuleItem = (AssetItem) linkedRuleItem1.getPrecedingVersion();
+		assertNotNull(predecessorRuleItem);
+		assertEquals(1, predecessorRuleItem.getCategories().size());
+		CategoryItem cat = (CategoryItem) predecessorRuleItem.getCategories()
+				.get(0);
+		assertEquals("LinkedAssetItemfoo", cat.getName());
+
+		assertEquals("test content", predecessorRuleItem.getContent());
+
+		assertEquals(RulesRepository.DEFAULT_PACKAGE, predecessorRuleItem
+				.getPackageName());
+
+		linkedRuleItem1.updateContent("newer lhs");
+		linkedRuleItem1.checkin("another");
+
+		predecessorRuleItem = (AssetItem) linkedRuleItem1.getPrecedingVersion();
+		assertNotNull(predecessorRuleItem);
+		assertEquals("new content", predecessorRuleItem.getContent());
+		predecessorRuleItem = (AssetItem) predecessorRuleItem
+				.getPrecedingVersion();
+		assertNotNull(predecessorRuleItem);
+		assertEquals("test content", predecessorRuleItem.getContent());
+
+		// now try restoring
+		long oldVersionNumber = ruleItem1.getVersionNumber();
+
+		AssetItem toRestore = getRepo().loadAssetByUUID(
+				predecessorRuleItem.getVersionSnapshotUUID());
+
+		getRepo().restoreHistoricalAsset(toRestore, linkedRuleItem1,
+				"cause I want to");
+
+		AssetItem restored = getRepo().loadDefaultPackage().loadAsset(
+				"LinkedAssetItemtestGetPrecedingVersion");
+
+		// assertEquals( predecessorRuleItem.getCheckinComment(),
+		// restored.getCheckinComment());
+		assertEquals(predecessorRuleItem.getDescription(), restored
+				.getDescription());
+		assertEquals("cause I want to", restored.getCheckinComment());
+		assertEquals(6, restored.getVersionNumber());
+		assertFalse(oldVersionNumber == restored.getVersionNumber());
+	}
+
+	public void testGetSucceedingVersion() {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetSucceedingVersion", "test description");
+		ruleItem1.checkin("version0");
+		assertEquals(1, ruleItem1.getVersionNumber());
+		
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestGetSucceedingVersion", ruleItem1.getUUID());
+		linkedRuleItem1.checkin("version1");	
+		assertEquals(2, linkedRuleItem1.getVersionNumber());
+		
+		AssetItem succeedingRuleItem = (AssetItem) linkedRuleItem1
+				.getSucceedingVersion();
+		assertTrue(succeedingRuleItem == null);
+
+		linkedRuleItem1.updateContent("new content");
+		linkedRuleItem1.checkin("la");
+
+		assertEquals(3, linkedRuleItem1.getVersionNumber());
+
+		AssetItem predecessorRuleItem = (AssetItem) linkedRuleItem1
+				.getPrecedingVersion();
+		assertEquals("", predecessorRuleItem.getContent());
+		succeedingRuleItem = (AssetItem) predecessorRuleItem
+				.getSucceedingVersion();
+		assertNotNull(succeedingRuleItem);
+		assertEquals(linkedRuleItem1.getContent(), succeedingRuleItem.getContent());
+	}
+
+	public void testGetSuccessorVersionsIterator() {
+		try {
+			AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+					"LinkedAssetItemtestGetSuccessorVersionsIterator", "test content");
+			ruleItem1.checkin("version0");
+			
+			AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+					"LinkedAssetItemlinkedtestGetSuccessorVersionsIterator", ruleItem1.getUUID());
+			linkedRuleItem1.checkin("version1");	
+			
+			Iterator iterator = linkedRuleItem1.getSuccessorVersionsIterator();
+			assertNotNull(iterator);
+			assertFalse(iterator.hasNext());
+
+			linkedRuleItem1.updateContent("new content").checkin("ya");
+
+			iterator = linkedRuleItem1.getSuccessorVersionsIterator();
+			assertNotNull(iterator);
+			assertFalse(iterator.hasNext());
+
+			AssetItem predecessorRuleItem = (AssetItem) linkedRuleItem1
+					.getPrecedingVersion();
+			iterator = predecessorRuleItem.getSuccessorVersionsIterator();
+			assertNotNull(iterator);
+			assertTrue(iterator.hasNext());
+			AssetItem nextRuleItem = (AssetItem) iterator.next();
+			assertEquals("new content", nextRuleItem.getContent());
+			assertFalse(iterator.hasNext());
+
+			linkedRuleItem1.updateContent("newer content");
+			linkedRuleItem1.checkin("boo");
+
+			iterator = predecessorRuleItem.getSuccessorVersionsIterator();
+			assertNotNull(iterator);
+			assertTrue(iterator.hasNext());
+			nextRuleItem = (AssetItem) iterator.next();
+			assertEquals("new content", nextRuleItem.getContent());
+			assertTrue(iterator.hasNext());
+			nextRuleItem = (AssetItem) iterator.next();
+			assertEquals("newer content", nextRuleItem.getContent());
+			assertFalse(iterator.hasNext());
+		} catch (Exception e) {
+			fail("Caught unexpected exception: " + e);
+		}
+	}
+
+	public void testGetPredecessorVersionsIterator() {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetPredecessorVersionsIterator", "test description");
+		ruleItem1.checkin("version0");
+
+		Iterator iterator = ruleItem1.getPredecessorVersionsIterator();
+		assertNotNull(iterator);
+		assertFalse(iterator.hasNext());
+		
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestGetPredecessorVersionsIterator", ruleItem1.getUUID());
+		linkedRuleItem1.checkin("version1");	
+
+		ruleItem1.updateContent("test content");
+		ruleItem1.checkin("lalalalala");
+
+		iterator = linkedRuleItem1.getPredecessorVersionsIterator();
+		assertNotNull(iterator);
+		assertTrue(iterator.hasNext());
+
+		ruleItem1.updateContent("new content");
+		ruleItem1.checkin("boo");
+
+		iterator = linkedRuleItem1.getPredecessorVersionsIterator();
+		assertNotNull(iterator);
+		assertTrue(iterator.hasNext());
+		AssetItem nextRuleItem = (AssetItem) iterator.next();
+
+		assertEquals("test content", nextRuleItem.getContent());
+
+		ruleItem1.updateContent("newer content");
+		ruleItem1.checkin("wee");
+
+		iterator = linkedRuleItem1.getPredecessorVersionsIterator();
+		assertNotNull(iterator);
+		assertTrue(iterator.hasNext());
+		nextRuleItem = (AssetItem) iterator.next();
+		assertTrue(iterator.hasNext());
+		assertEquals("new content", nextRuleItem.getContent());
+		nextRuleItem = (AssetItem) iterator.next();
+
+		assertEquals("test content", nextRuleItem.getContent());
+
+		assertEquals("", ((AssetItem) iterator.next()).getContent());
+
+	}
+
+	public void testHistoryIterator() throws Exception {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestHistoryIterator", "test description");
+		ruleItem1.checkin("version0");
+		
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestHistoryIterator", ruleItem1.getUUID());
+		linkedRuleItem1.checkin("version1");	
+		
+		ruleItem1 = getRepo().loadAssetByUUID(linkedRuleItem1.getUUID());
+		ruleItem1.updateContent("wo");
+		ruleItem1.checkin("version2");
+
+		ruleItem1 = getRepo().loadAssetByUUID(ruleItem1.getUUID());
+		ruleItem1.updateContent("ya");
+		ruleItem1.checkin("version3");
+
+		Iterator it = ruleItem1.getHistory();
+		for (int i = 0; i < 3; i++) {
+			assertTrue(it.hasNext());
+			it.next();
+		}
+	}
+
+	public void testGetTitle() {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetTitle", "test content");
+		
+		AssetItem linkedRuleItem1 = getDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestGetTitle", ruleItem1.getUUID());		
+
+		assertEquals("LinkedAssetItemlinkedtestGetTitle", linkedRuleItem1.getName());
+		assertEquals("LinkedAssetItemtestGetTitle", ruleItem1.getName());
+		//NOTE: LinkedAssetItem does not have its own Title property.
+		assertEquals("LinkedAssetItemtestGetTitle", linkedRuleItem1.getTitle());
+		assertEquals("LinkedAssetItemtestGetTitle", ruleItem1.getTitle());
+	}
+
+	public void testDublinCoreProperties() {
+		PackageItem pkg = getRepo().createPackage("LinkedAssetItemtestDublinCore", "wa");
+
+		AssetItem ruleItem = pkg.addAsset("LinkedAssetItemtestDublinCoreProperties",
+				"yeah yeah yeah");
+		ruleItem.checkin("woo");
+		
+		AssetItem linkedRuleItem1 = pkg.addLinkedAsset(
+				"LinkedAssetItemlinkedtestDublinCoreProperties", ruleItem.getUUID());
+		
+		linkedRuleItem1.updateCoverage("b");
+		assertEquals("b", linkedRuleItem1.getCoverage());
+		linkedRuleItem1.checkin("woo");
+
+		ruleItem = getRepo().loadPackage("LinkedAssetItemtestDublinCore").loadAsset("LinkedAssetItemtestDublinCoreProperties");
+		assertEquals("b", ruleItem.getCoverage());
+		assertEquals("", ruleItem.getExternalRelation());
+		assertEquals("", ruleItem.getExternalSource());
+		
+		ruleItem = getRepo().loadPackage("LinkedAssetItemtestDublinCore").loadAsset("LinkedAssetItemlinkedtestDublinCoreProperties");
+		assertEquals("b", ruleItem.getCoverage());
+		assertEquals("", ruleItem.getExternalRelation());
+		assertEquals("", ruleItem.getExternalSource());
+	}
+
+	public void testGetFormat() throws Exception {
+		AssetItem ruleItem1 = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestGetFormat", "test content");
+		
+		AssetItem linkedRuleItem1 = getRepo().loadDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestGetFormat", ruleItem1.getUUID());
+		
+		linkedRuleItem1.updateContent("la");
+		assertEquals(AssetItem.DEFAULT_CONTENT_FORMAT, linkedRuleItem1.getFormat());
+
+		assertTrue(linkedRuleItem1.getNode().hasProperty(
+				AssetItem.CONTENT_PROPERTY_NAME));
+		assertFalse(linkedRuleItem1.getNode().hasProperty(
+				AssetItem.CONTENT_PROPERTY_BINARY_NAME));
+
+		linkedRuleItem1.updateFormat("blah");
+		assertEquals("blah", linkedRuleItem1.getFormat());
+	}
+
+	public void testAnonymousProperties() {
+		AssetItem item = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemanonymousproperty", "lalalalala");
+		
+		AssetItem linkedRuleItem1 = getRepo().loadDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedanonymousproperty", item.getUUID());
+		
+		linkedRuleItem1.updateUserProperty("fooBar", "value");
+		assertEquals("value", linkedRuleItem1.getUserProperty("fooBar"));
+
+		linkedRuleItem1.checkin("lalalala");
+		try {
+			linkedRuleItem1.updateUserProperty("drools:content", "whee");
+			fail("should not be able to set built in properties this way.");
+		} catch (IllegalArgumentException e) {
+			assertNotNull(e.getMessage());
+		}
+	}
+
+	public void testBinaryAsset() throws Exception {
+		AssetItem item = getRepo().loadDefaultPackage().addAsset(
+				"LinkedAssetItemtestBinaryAsset", "yeah");
+		
+		AssetItem linkedRuleItem1 = getRepo().loadDefaultPackage().addLinkedAsset(
+				"LinkedAssetItemlinkedtestBinaryAsset", item.getUUID());
+		
+		String data = "abc 123";
+		ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
+		linkedRuleItem1.updateBinaryContentAttachment(in);
+		linkedRuleItem1.updateBinaryContentAttachmentFileName("x.x");
+		in.close();
+
+		assertEquals(data, linkedRuleItem1.getContent());
+
+		assertFalse(linkedRuleItem1.getNode().hasProperty(AssetItem.CONTENT_PROPERTY_NAME));
+		assertTrue(linkedRuleItem1.getNode().hasProperty(
+				AssetItem.CONTENT_PROPERTY_BINARY_NAME));
+		linkedRuleItem1.checkin("lalalala");
+
+		assertTrue(linkedRuleItem1.isBinary());
+
+		item = getRepo().loadDefaultPackage().loadAsset("LinkedAssetItemtestBinaryAsset");
+		InputStream in2 = item.getBinaryContentAttachment();
+		assertNotNull(in2);
+
+		byte[] data2 = item.getBinaryContentAsBytes();
+		assertEquals(data, new String(data2));
+		assertEquals("x.x", item.getBinaryContentAttachmentFileName());
+		assertTrue(item.isBinary());
+
+		linkedRuleItem1.updateContent("qed");
+		linkedRuleItem1.checkin("");
+		item = getRepo().loadAssetByUUID(item.getUUID());
+		assertEquals("qed", item.getContent());
+	}
+
+}


Property changes on: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/LinkedAssetItemTest.java
___________________________________________________________________
Name: svn:keywords
   + Rev Date
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java
===================================================================
--- labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java	2009-09-25 16:43:17 UTC (rev 29474)
+++ labs/jbossrules/trunk/drools-repository/src/test/java/org/drools/repository/PackageItemTest.java	2009-09-26 05:05:11 UTC (rev 29475)
@@ -80,9 +80,6 @@
 
         int n_ = iteratorToList(repo.listPackages()).size();
         assertEquals(n - 1, n_);
-
-
-
     }
 
     public void testRulePackageItem() throws Exception {
@@ -103,13 +100,8 @@
             }
         }
         fail("should have picked up the testRulePackage but didnt.");
-
-
     }
 
-
-
-
     /**
      * This is showing how to copy a package with standard JCR
      */
@@ -143,7 +135,6 @@
         it1.checkin( "la" );
         it1_ = pkg2.loadAsset( "testPackageCopy1" );
         assertEquals("new content", it1_.getContent());
-
     }
 
     public void testPackageSnapshot() throws Exception {
@@ -254,8 +245,6 @@
 
         assertEquals("BOO", res[0]);
         assertEquals("BOO2", res[1]);
-
-
     }
 
     private RulesRepository getRepo() {
@@ -345,7 +334,6 @@
         AssetItem prior = (AssetItem) rules.get( 0 );
 
         assertFalse("new content".equals( prior.getContent() ));
-
     }
 
     public void testIgnoreState() throws Exception {
@@ -385,7 +373,6 @@
         } catch (RulesRepositoryException e) {
             assertNotNull(e.getMessage());
         }
-
     }
 
     public void testPackageInstanceWrongNodeType() throws Exception {
@@ -398,10 +385,8 @@
         } catch (RulesRepositoryException e) {
             assertNotNull(e.getMessage());
         }
-
     }
 
-
     public void testLoadRulePackageItemByUUID() throws Exception {
 
         PackageItem rulePackageItem = getRepo().createPackage("testLoadRuleRuleItemByUUID", "desc");
@@ -461,10 +446,40 @@
             rules = iteratorToList(rulePackageItem1.getAssets());
             assertNotNull(rules);
             assertEquals(2, rules.size());
-
     }
 
+    public void testAddLinkedRuleRuleItem() {
+        PackageItem rulePackageItem1 = getRepo().createPackage("testAddLinkedRuleRuleItem","desc");
 
+        AssetItem ruleItem1 = rulePackageItem1.addAsset("testAddLinkedRuleRuleItem", "test description");
+        ruleItem1.updateContent( "test content" );
+        ruleItem1.checkin( "updated the rule content" );
+        
+        AssetItem linkedRuleItem1 = rulePackageItem1.addLinkedAsset("linkedTestAddLinkedRuleRuleItem", ruleItem1.getUUID(), null);
+        linkedRuleItem1.updateContent( "test content for linked" );
+        linkedRuleItem1.checkin( "updated the rule content for linked" );       
+
+        Iterator rulesIt1 = rulePackageItem1.getAssets();
+        List rules1 = iteratorToList( rulesIt1 );
+        assertEquals(2, rules1.size());    
+ 
+        //test that it is following the head revision
+        ruleItem1.updateContent("new lhs");
+        ruleItem1.checkin( "updated again" );        
+        
+        Iterator rulesIt2 = rulePackageItem1.getAssets();
+        List rules2 = iteratorToList( rulesIt2 );
+        assertEquals(2, rules2.size());
+        
+        while(rulesIt2.hasNext()) {
+        	AssetItem ai = (AssetItem)rulesIt2.next();
+            assertTrue(ai.getName().equals("testAddLinkedRuleRuleItem") || ai.getName().equals("linkedTestAddLinkedRuleRuleItem"));
+            assertEquals("new lhs", ai.getContent());
+            assertEquals("test description", ai.getDescription());    
+            assertEquals("updated again", ai.getCheckinComment());  
+        }        
+    }
+    
     List iteratorToList(Iterator it) {
         List list = new ArrayList();
         while(it.hasNext()) {
@@ -473,12 +488,6 @@
         return list;
     }
 
-
-
-
-
-
-
     public void testGetRules() {
             PackageItem rulePackageItem1 = getRepo().createPackage("testGetRules", "desc");
 
@@ -510,8 +519,6 @@
             assertNotNull(loaded);
             assertEquals("testGetRules", loaded.getName());
             assertEquals("desc", loaded.getDescription());
-
-
     }
 
     public void testToString() {
@@ -521,7 +528,6 @@
             ruleItem1.updateContent( "test lhs content" );
 
             assertNotNull(rulePackageItem1.toString());
-
     }
 
     public void testRemoveRule() {
@@ -561,7 +567,6 @@
             rules = iteratorToList(rulePackageItem1.getAssets());
             assertNotNull(rules);
             assertEquals(0, rules.size());
-
     }
 
     public void testSearchByFormat() throws Exception {
@@ -602,7 +607,6 @@
         assertTrue(list2.get( 0 ) instanceof AssetItem);
         assertTrue(list2.get( 1 ) instanceof AssetItem);
         assertTrue(list2.get( 2 ) instanceof AssetItem);
-
     }
 
     public void testListArchivedAssets() throws Exception {
@@ -641,8 +645,6 @@
 
         list = iteratorToList( it );
         assertEquals(4, list.size());
-
-
     }
 
     public void testExcludeAssetTypes() throws Exception {
@@ -674,8 +676,6 @@
         it = pkg.listAssetsNotOfFormat(new String[] {"drl", "xls"});
         ls = iteratorToList(it);
         assertEquals(0, ls.size());
-
-
     }
 
     public void testSortHistoryByVersionNumber() {
@@ -706,8 +706,6 @@
         item = getRepo().loadPackage("testHeader");
         assertEquals("new header", getHeader(item));
         assertEquals("boo", item.getExternalURI());
-
-
     }
 
     public void testGetFormatAndUpToDate() {
@@ -731,7 +729,6 @@
     	}
 		as.updateContent(h);
 		//as.checkin("");
-
     }
 
     public static String getHeader(PackageItem pkg) {
@@ -772,7 +769,6 @@
         getRepo().save();
 
         assertEquals(v, item.getVersionNumber());
-
     }
 
     static class MockAssetItem extends AssetItem {



More information about the jboss-svn-commits mailing list