Saturday, December 22, 2012

Flex: Displayable Image from an Image Resource

  Following is a class which can be used to convert and an image resource (here a png file) to a displayable image (mx.controls.Image) instance in Flex. Here a static function 'displayableImageFromClass(Image, int, int): void ' does the work. The function's height and width parameters are optional and they specify the height and width of the displayable image that is returned.

================================================================

package com.shyarmal.drawing.utils {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.utils.ByteArray;
   
    import mx.controls.Image;
    import mx.graphics.codec.PNGEncoder;
   

    public class ImageUtils {
       
        /**
         * png image encoder.
         */
        private static var encoder:PNGEncoder = new PNGEncoder();
       
        public function ImageUtils() {
        }
       
        /**
         * Given a class (with an embeded png image), 
         * creates a corresponding displayable image,
         * if imageClass is not null.
         *
         * @param imageClass - The image class from 
         *            which the image has to be created.
         * @param height - Height of the final image (optional).
         * @param width - Width of the final image (optional).
         * @return - mx.controls.Image produced.
         */
        public static function displayableImageFromClass( 
                   imageClass: Class, height: int = 25, 
                                   width: int = 25): Image {
            var i:Image = new Image();
            if (imageClass != null) {
                var bitMap: Bitmap = new imageClass();
                var bitmapData: BitmapData = bitMap.bitmapData;
                bitmapData.draw(bitMap);
                var imageToDisplay:ByteArray = 
                         encoder.encode(bitmapData);
                i.source = imageToDisplay;
                i.height = height;
                i.width = width;
            }
            return i;
        }
    }
}

================================================================

  If the 'imageClass' parameter is null, simply a new instance of mx.controls.Image is formed and returned. If not a 'Bitmap' is formed by instantiating the 'imageClass' passed in. Then its 'BitmapData' is derived. A byte array is constructed with the help of PNGEncoder and assigned to the source of the image instance. Image is returned after setting its dimensions.

Invocation of the method can be done as below;

[Embed (source="/assets/images/your_png.png" )] 
var resource: Class; // define a class with the actual resource.

// height and width can be passed if necessary.
var i:Image = ImageUtils.displayableImageFromClas(resource);



thanks,
Shyarmal.

Thursday, December 13, 2012

Distinguish 'double click' from 'click' in Flex

   Defining behavior for both 'click' and 'double click' events in Flex is tricky, as when a double click is done, the click event gets fired. Therefore there needs to be a workaround to solve this issue. First of all add event listeners for 'click' and 'double click' (this can be done either in mxml or actionscrips which I have chosen the later).


//Adding click listener
component.addEventListener(MouseEvent.CLICK, localMouseClickEvent, false, 0, true);

//Adding double click listener
component.addEventListener(MouseEvent.DOUBLE_CLICK, localMouseDoubleClickedEvent, false, 0, true);

//n.b. here component refers to any mx UIComponent 


   According to the code above if a mouse click is issued, 'localMouseClickEvent(MouseEvent)' method is called and for a double click, 'localMouseDoubleClickedEvent(MouseEvent)' should be called. However, when a double click is done, 'localMouseClickEvent(MouseEvent)' triggers.Both functions are defined below. 


/** reference to the deferred click operation */
private var deferredClickReference: Number = 0;


protected function localMouseClickEvent (event: MouseEvent) : void {    
          clearInterval(deferredClickReference); // clearing previous schedule
         
          // defer operation                   
          deferredClickReference = setInterval(deferredMouseClickEvent, 300); 
}
   
protected function deferredMouseClickEvent() : void {
        clearInterval(deferredClickReference); // clearing previous schedule  
        
       // code to execute for 'click'
}

protected function localMouseDoubleClickedEvent(event:MouseEvent):void {
         // revoking deferred click operation
         clearInterval(deferredClickReference);

        // code to execute for 'double click'
}


   The workaround is to defer the single click operations to see if it is actually followed by another click. Another function, 'deferredMouseClickEvent()' is defined, and invoked from localMouseClickEvent(event: MouseEvent0)' scheduled to be triggered after 300 ms. This scheduling is done by 'setInterval(deferredMouseClickEvent, 300)' , which returns a reference to the schedule (this is assigned to 'deferredClickReference'). So if a click is followed by another within 300 ms, double click event operations will be run, otherwise that of click
   'clearInterval(deferredClickReference)' resets the reference, which revokes the scheduled single click operation. This is done before scheduling the deferred operation, after execution of the same and in double click event's function (to prevent deferredMouseClickEvent() run).


 thanks,
Shyarmal.

Wednesday, December 5, 2012

Delete XML nodes in Flex

This is about deleting a node from XML in Flex. Here our XML is assigned to a variable, treeXml.

var treeXml: XML = <root>
                       <node label="abc">
                             <node label="Page"></node>
                             <node label="Business"></node>
                             <node label="Application"></node>
                             <node label="Loyalty"></node>
                        </node>
                        <node label="def">
                             <node label="Page"></node>
                             <node label="Business"></node>
                             <node label="Application"></node>
                             <node label="Loyalty"></node>
                        </node> 
                     </root>

Suppose we need to delete the node with label 'abc'. The way to do it is;

delete treeXml.node.(@label=="abc")[0];

Above code deletes the child (node) which is having the attribute label equal to 'abc'. Notice '[0]' at the end of the statement. After this, treeXml would be;

                    <root>
                         <node label="def">
                              <node label="Page"></node>
                              <node label="Business"></node>
                              <node label="Application"></node>
                              <node label="Loyalty"></node>
                         </node> 
                    </root>

Thanks,
Danuka.




Monday, October 22, 2012

Flex - Changing Cursor Icon

Mouse icon can be changed in flex. This example changes the cursor icon to a configured image when mouse is moved over it and then resets it to system cursor on mouse moves out. I have posted the action script code here.

==================================================================

    [Embed(source="assets/images/tree_move.png")]
    private var treeCursorIcon: Class;  //define an icon

    public function changeToTreeCursor (e: flash.events.MouseEvent) : void { 
            CursorManager.setCursor(treeCursorIcon); // change the cursor here
    }

    private function changeToDefaultCursor() : void {
        CursorManager.removeAllCursors(); // reset the cursor here
    }

==================================================================
First an your icon has to be defined, providing the relative path to the image. The function, changeToTreeCursor(MouseEvent) sets that icon as the mouse cursor and changeToDefaultCursor() sets it back to system cursor.

You can have your own custom component as follows, and define rollOut and rollOver attributes of it to fire changeToTreeCursor(MouseEvent) and changeToDefaultCursor() methods respectively for the corresponding events to fire.

==================================================================

<xxx:My_Component id="my_comp" x="0" y="39" title="@Resource(key='comp_label', bundle='draw')" rollOut="changeToDefaultCursor()" rollOver="changeToTreeCursor(event)">
    </xxx:My_Component>

==================================================================

thanks,
Shyarmal.

Saturday, October 20, 2012

Customizing Flash Right- Click Menu


   The menu which appears on right click of a flash object can be customized to include items of your choice. The following code segment adds options, "Expand", "Hide Outcomes", "Hide Inputs", "Hide Outputs", "Hide Privileges" and "Keys Only" to the menu. Further it removes/ hides some existing items of the menu. Code segment to do this is posted below.

================================================================

            var contextMenu: ContextMenu = new ContextMenu();
            contextMenu.hideBuiltInItems();
            contextMenu.clipboardMenu = false;   
            var showAll : ContextMenuItem = new ContextMenuItem("Expand");
            var hideOutcomes : ContextMenuItem = new ContextMenuItem("Hide Outcomes");
            var hideInputs : ContextMenuItem = new ContextMenuItem("Hide Inputs");
            var hideOutputs : ContextMenuItem = new ContextMenuItem("Hide Outputs");
            var hidePrivileges : ContextMenuItem = new ContextMenuItem("Hide Privileges");
            var hideAll : ContextMenuItem = new ContextMenuItem("Keys Only");
            showAll.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleShowAll);
            hideOutcomes.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleHideOutcomes);
            hideInputs.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleHideInput);
            hideOutputs.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleHideOutput);
            hidePrivileges.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleHidePrivileges);
            hideAll.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,      handleHideAll);
            contextMenu.customItems.push(showAll);
            contextMenu.customItems.push(hideOutcomes);
            contextMenu.customItems.push(hideInputs);
            contextMenu.customItems.push(hideOutputs);
            contextMenu.customItems.push(hidePrivileges);
            contextMenu.customItems.push(hideAll);

            component.contextMenu = contextMenu;  
            // component is of type mx.core.UIComponent

================================================================

   First a 'flash.ui.ContextMenu' instance is created. Subsequently, its inbuilt and clip board items are removed [contextMenu.hideBuiltInItems(); contextMenu.clipboardMenu = false;]. Then new menu items are created and added to the menu. Each menu items is registered with an event listener to be fired when the same is selected.
  For an example, it "Hide Outputs" item is selected the following method will be triggered.

private function handleHideOutcomes (event: ContextMenuEvent) : void {
        // operational code

}

Finally, the menu created this way is assigned as the context menu of the respective UI component (mx.core.UIComponent). Following is the figure of the right click menu.


thanks,
Shyarmal.

Friday, September 28, 2012

Flex Popup Window


 This is about how a popup window can be created to appear to the right side, with a mouse click. I have used a button bar in this code sample which would be positioned vertically and contain an image icon. Further, the button bar will dispatch an item clicked event when any of it's items is clicked. What appears subsequently is a tiled window, that would dispatch an event to hide itself when exit (x) is clicked.

 The methods to be executed when events are fired are written in a separate action script, my_action_script.as which is included in my mxml file with the line, <mx:Script source="my_action_script.as"/>. 
===================================================================

 <!--
     Code that is not relevant is omitted.
-->
<mx:Script source="my_action_script.as"/>

<mx:Array id="buttons">

        <mx:Object icon="@Embed(source='images/my_image.png')" desc="test"/>   
 </mx:Array>

 <!--
     Code that is not relevant is omitted.
-->
<mx:ButtonBar height="100%" width="2%" verticalGap="2" direction="vertical" id="buttonBar" dataProvider="{buttons}" itemClick="buttonBar_itemClick(event);" paddingTop="0" paddingBottom="{this.height - 75}" />
               
            <s:PopUpAnchor height="{buttonBar.height}" width="0"
                       popUpPosition="right" id="popAnc">
                  <s:TitleWindow id="title_window"                                                              title="XXX"   close="popUpAnchorCloseHandler(event);">
                    <mx:Panel id="my_panel" height="{buttonBar.height - acb.height}" 
                              width="{acb.width/4}" title="my panel" alpha="1">
                        <!-- add items to the panel here -->
                    </mx:Panel>
                </s:TitleWindow>
            </s:PopUpAnchor>

 <!--

     Code that is not relevant is omitted.
-->

===================================================================

 First, an array with one object, having an icon is defined. This array is the data provider of the button bar. The direction of the button bar is vertical. If an item of the button bar is clicked (in this case there is only one item) the method, buttonBar_itemClick(e:ItemClickEvent) will be called (since it is defined as itemClicked attribute).
 Popup anchor is the component used for popup. It can be customized by introducing where to popup with height, width and popUpPosition attributes. The window will appear to the right as stated in popUpPosition. This UI component engulfs a title window containing a panel. The title window will trigger popUpAnchorCloseHandler(e: CloseEvent) method as stated for it's close attribute.

 Actionscript code segments pertinent to the example are posted below.
===================================================================


/**
     * This is called when an item of the button bar is clicked.
     */
    private function buttonBar_itemClick(e:ItemClickEvent):void {
        var message:String = ObjectUtil.toString(e.item);
        if (message.indexOf("test1") != -1) {
            // open the pop-up anchor.
            FlexGlobals.topLevelApplication.popAnc.displayPopUp = true;
        }
    }

    /**
     * This is called when the title window's close event is fired.
     * Pop up anchor is closed here.
     */
    private function popUpAnchorCloseHandler(e: CloseEvent): void {
        FlexGlobals.topLevelApplication.popAnc.displayPopUp = false;
    }

===================================================================

 The first method, which is invoked when the item is clicked, converts the item into a string format and checks if "test1" is available ("test1" is the value of desc attribute of the item). If so, popup anchor is made visible. The second method will be invoked when the 'x' sign of the title window is clicked and it will make the anchor invisible.

thanks,
Shyarmal.

Monday, September 24, 2012

Flex Datagrid Example

This is a simple implementation of a data grid in Flex. It would have three columns and 2 rows. Data to be contained in the grid is initialized at application start up and bound to the same. The method, initData(), which initialized the data for the grid, is called at application start up as it is defined in the "initialize" attribute of "s:Application".

============================================================= 
<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               minWidth="955" minHeight="600" 
               initialize="initData();">

    <fx:Declarations>
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import mx.collections.*;

            private var dataArray: Array = [
                {Artist:'Danuka', Album:'storm', Price:17.97}, 
                {Artist:'Shyarmal', Album:'gloomy', Price:96.29}
            ];  

            [Bindable]
            public var gridData: ArrayCollection;
            public function initData(): void {
                gridData = new ArrayCollection(dataArray);
            }

        ]]>
    </fx:Script>
     

    <s:DataGrid id="my_grid" width="500" 
         height="500" dataProvider="{gridData}">
    </s:DataGrid>

</s:Application>

=============================================================

<s:DataGrid id="my_grid" width="500" height="500" dataProvider="{gridData}"></s:DataGrid> introduces a flex grid. The attribute dataProvider binds data to the grid. In this example, "gridData" is an ArrayCollection holding that data, which is initialized through initData() method. In the method, gridData is initialized with a predefined array (dataArray). The symbol, [Bindable] above gridData makes it a source to be bound to a component (This enables gridData to be used as the source of data of the grid).

Output:



thanks,
Shyarmal.

Flex "Hello World" Application

This is my first mxml script. Here I have used a label to display "Hello World". This is a flex web application.

==================================================================
<?xml version="1.0" encoding="utf-8"?>

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               minWidth="955" minHeight="600">

    <fx:Declarations>
    </fx:Declarations>

    <s:Label id="lb" x="350" y="350" text="hello world" />

</s:Application>

==================================================================

     <s:Label id="lb" x="350" y="350" text="hello world" /> - introduces a label component to the application. [id is the attribute by which this component will be referred, x and y define the coordinates and text holds what's to display. ]

This mxml is further enhanced, adding a button which will change the text of the label.

==================================================================
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               minWidth="955" minHeight="600">

    <fx:Declarations>

    </fx:Declarations>

    <s:Label id="lb" x="350" y="350" text="hello world" />
    <s:Button id="btn" x="350" y="400" 
        label="click" click="changeLabel();"/>
    <fx:Script>
        <![CDATA[
             private function changeLabel() : void {
                if (lb.text == "hello world")
                    lb.text = "good bye ..";
                else 
                    lb.text = "hello world";
            }
         ]]>
    </fx:Script>

</s:Application>

==================================================================

Here,     <s:Button id="btn" x="350" y="400" label="click" click="changeLabel();"/>  adds a button component to the application. [id is the attribute by which this component will be referred, x and y define the coordinates and label is the caption and click triggers a function that is to be called when the button is clicked. ]

fx:Script encloses actionscript code in an mxml script. Here a function, changeLabel() is defined, which is to be called when a user clicks on the button (The function is bound to "on click" event of the button). This function changes the text of the label to "good bye .." if it is "hello world" and visa-verse.


thanks,
Shyarmal.

Saturday, September 8, 2012

Configure remote repository for Maven

Remote repository can be changed by configuring settings.xml in conf folder of maven. 

<?xml version="1.0" encoding="UTF-8"?>


<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <!--
  Maven local repository defaults to ~/.m2/repository.
To change the path to the local repository, have the following tag.
  -->
 <localRepository>/path/to/local/repo</localRepository>


  <pluginGroups>
  </pluginGroups>
  <proxies>
    <proxy>
      <id>optional</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypass</password>
      <host>proxy.host.net</host>
      <port>80</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
  </proxies>

  <servers>

    <!-- 
To configure your credentials to access the remote repository
    -->
    <server>
      <id>xxxxx</id>
      <username>your_username</username>
      <password>your_password</password>
    </server>

  </servers>


  <mirrors>

    <!--
Remote repository can be configured here.
     -->
    <mirror>
      <id>artifactory</id>
      <mirrorOf>*</mirrorOf>
      <name>my repo name</name>
      <url>https://www.location_of_my_repo/repo</url>
    </mirror>

  </mirrors>

  <profiles>
    <!-- profile
    <profile>
      <id>jdk-1.4</id>
      <activation>
        <jdk>1.4</jdk>
      </activation>
      <repositories>
        <repository>
          <id>jdk14</id>
          <name>Repository for JDK 1.4 builds</name>
          <url>http://www.myhost.com/maven/jdk14</url>
          <layout>default</layout>
          <snapshotPolicy>always</snapshotPolicy>
        </repository>
      </repositories>
    </profile>
    -->
  </profiles>
</settings>

thanks,
Shyarmal.

Sunday, August 19, 2012

Hibernate enum mapping - hmb

The following example shows how to map enums using hbm files. Media is the enum which is mapped in this means. It has a 'description' attribute which will be saved in the database. The methods 'getDescription()' and 'getMedia(String)' are used to retrieve the description and the media of 'Media' respectively. Notice the latter is static and returns corresponding enum type of the value passed into it.

==============================================================
package com.shyarmal.hibernate.example.model;

public enum Media {

    PRINTED("PRINTED"), ELECTRONIC("ELECTRONIC"), UNKNOWN("UNKNOWN");
    private String description;

    Media(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public static Media getMedia(String value) {
        if ("PRINTED".equals(value)) {
           return PRINTED;
        } else if ("ELECTRONIC".equals(value)) {
           return ELECTRONIC;
        } else {
            return UNKNOWN;
        }
    }
}
==============================================================

A custom enum user type is defined below, implementing the interfaces UserType and ParameterizedType. Parameters of the typedef element of the hbm (found below) are used in 'setParameterValues(Properties)' to initialize the enum type and it's methods. The methods  nullSafeGet(ResultSet rs, String[] names, Object owner)and nullSafeGet(ResultSet rs, String[] names, Object owner) are used to get and set the enum from and to the database.

==============================================================

package com.shyarmal.hibernate.example.model;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.type.NullableType;
import org.hibernate.type.TypeFactory;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class EnumUserType implements UserType, ParameterizedType {

    private static final String IDENTIFIER_METHOD = "name";
    private static final String VALUE_OF_METHOD = "valueOf";
    private Class<? extends Enum> enumClass;
    private Class<?> identifierType;
    private Method identifierMethod;
    private Method valueOfMethod;
    private NullableType type;
    private int[] sqlTypes;

    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enumClass");
        try {
            enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
        } catch (ClassNotFoundException cfne) {
            throw new HibernateException("Enum class not found", cfne);
        }

        String identifierMethodName = parameters.getProperty("identifierMethod", IDENTIFIER_METHOD);
        try {
            identifierMethod = enumClass.getMethod(identifierMethodName, new Class[0]);
            identifierType = identifierMethod.getReturnType();
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain identifier method", e);
        }

        type = (NullableType) TypeFactory.basic(identifierType.getName());
        if (type == null)
            throw new HibernateException("Unsupported identifier type " + identifierType.getName());
        sqlTypes = new int[]{Hibernate.STRING.sqlType()};
        String valueOfMethodName = parameters.getProperty("valueOfMethod", VALUE_OF_METHOD);
        try {
            valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[]{identifierType});
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain valueOf method", e);
        }
    }

    public Class returnedClass() {
        return enumClass;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        Object identifier = type.get(rs, names[0]);
        if (rs.wasNull()) {
            return null;
        }

        try {
            return valueOfMethod.invoke(enumClass, new Object[]{identifier});
        } catch (Exception e) {
            throw new HibernateException("Error in valueOf method '" + valueOfMethod.getName()
                    + "' of " + "enum class '" + enumClass + "'", e);
        }
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        try {
            if (value == null) {
                st.setNull(index, type.sqlType());
            } else {
                Object identifier = identifierMethod.invoke(value, new Object[0]);
                type.set(st, identifier, index);
            }
        } catch (Exception e) {
            throw new HibernateException("Error in identifierMethod '" + identifierMethod.getName()
                    + "' of " + "enum class '" + enumClass + "'", e);
        }
    }

    public int[] sqlTypes() {
        return sqlTypes;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return x == y;
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public boolean isMutable() {
        return false;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

==============================================================

I have posted the hbm file below. Only the configurations relevant to the type mapping is present. A type should be defined first, which is done with the 'typedef' element. So a type, 'media' is defined providing the class above, EnumUserType. Parameters 'enumClass', 'identifierMethod' and 'valueOfMethod' are defined. The parameter 'enumClass' is our enum, Media. Other two parameters, identifierMethod and valueOfMethod are the methods getDescription() and getMedia(String) respectively.

==============================================================

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.shyarmal.hibernate.example.model">

    <typedef name="media" class="com.shyarmal.hibernate.example.model.EnumUserType">
        <param name="enumClass">com.shyarmal.hibernate.example.model.Media</param>
        <param name="identifierMethod">getDescription</param>
        <param name="valueOfMethod">getMedia</param>
    </typedef>

    <class name="Xxxxx" table="XXXX_XXX">
        <!--
            ---- Other property definitions. ----
        -->           
        <property name="media" column="MEDIA" type="media"/>
    </class>

</hibernate-mapping>

==============================================================

After defining a type as described above, a property should be defined for the class (here it's Xxxxx), which should have an attribute called media of type 'Media' (our enum). So '<property name="media" column="MEDIA" type="media"/>' says that the property 'media' of the class Xxxxx of type 'media' (our defined type using typedef) will be mapped to 'MEDIA' column of 'XXXX_XXX' table in the database.


reference: using-enum-hibernate

thanks,
Shyarmal.

Sunday, August 12, 2012

Hibernate Hierarchy Mapping - Table Per Class

This example shows how to map a hierarchy with hibernate using the strategy, table per class. Circle and Square are two classes which extend Shape. The attribute, id of Shape is common to both the subclasses and will be the primary key of the tables created.

===================================================================
// The shape class
package com.shyarmal.hibernate.example.shape;

public class Shape implements IPersistable {

    protected long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
}


// Subclass of Shape, Circle
package com.shyarmal.hibernate.example.shape;

public class Circle extends Shape {

    private float radius;
    private float centerX;
    private float centerY;

    public float getRadius() {
        return radius;
    }

    public void setRadius(float radius) {
        this.radius = radius;
    }

    public float getCenterX() {
        return centerX;
    }

    public void setCenterX(float centerX) {
        this.centerX = centerX;
    }

    public float getCenterY() {
        return centerY;
    }

    public void setCenterY(float centerY) {
        this.centerY = centerY;
    }
}


// Subclass of Shape, Square
package com.shyarmal.hibernate.example.shape;

public class Square extends Shape {

    private float length;
    private float topX;
    private float topY;

    public float getTopX() {
        return topX;
    }

    public void setTopX(float topX) {
        this.topX = topX;
    }

    public float getlength() {
        return length;
    }

    public void setlength(float length) {
        this.length = length;
    }

    public float getTopY() {
        return topY;
    }
    public void setTopY(float topY) {
        this.topY = topY;
    }
}

===================================================================
The hibernate xml mapping for the above hierarchy is as follows. All three classes mapping configurations are done in the same hmb file. This configuration will map (and/or create) three tables for the three classes.

===================================================================
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.shyarmal.hibernate.example.shape">
    <class name="Shape" table="SHAPE">
        <id name="id" column="ID" type="long">
            <generator class="native" />
        </id>
        <joined-subclass table="CIRCLE" name="Circle">
            <key column="ID" />
            <property name="radius" column="RADIUS" type="float"/>
            <property name="centerX" column="CENTER_X" type="float"/>
            <property name="centerY" column="CENTER_Y" type="float"/>
        </joined-subclass>
        <joined-subclass table="SQUARE" name="Square">
            <key column="ID" />       
            <property name="length" type="float" column="LENGTH"/>
            <property name="topY" column="TOP_Y" type="float" />
            <property name="topX" column="TOP_X" type="float" />
        </joined-subclass>
    </class>
</hibernate-mapping>

===================================================================

As you can notice, the 'class' tag refers to the class, Shape and the primary key is it's id attribute  (mapped with 'generator' tag). Subclasses are mapped with the element, 'joined-subclass', enclosed in 'class' tag. The element, 'key' defines a (foreign key) reference to the 'ID' column of the 'SHAPE' table. Further, the properties specific to each subclass is defined within the 'joined-subclass' element.

thanks,
Shyarmal.