An open API service indexing awesome lists of open source software.

https://github.com/babyfish-ct/babyfish


https://github.com/babyfish-ct/babyfish

Last synced: 6 months ago
JSON representation

Awesome Lists containing this project

README

          

# Select language: English | Chinese

# What's BabyFish
BabyFish is a Java Framework that can let developers create smart data structure only with declartion code.
It have many functionalities, please view the following picture to know its general architecture.

# Architecture


In the picture, 5 functionalities are marked by red star:


, they are the most most important 5 functionalities of BabyFish.

# Java environment requirement
BabyFish1.1 requires Java8.

# Offline documents



Document
Description




tutorial.html(English)

Describes some important functions in detail, with both characters and illustrations
(Please use high version IE or other browsers to open it).



tutorial_zh_CN.html(Chinese)


demo-guide.html(English)

Introduces each demo one by one, and gives the recommended reading order
(Please use high version IE or other browsers to open it).



demo-guide_zh_CN.html(Chinese)

# Functionalities



  • 1. Java Functionalities




    • 1.1. Basic Functionalities




      • 1.1.1. Typed I18N


        Better way to support I18N. Be different with "java.util.ResourceBundle" that reports the
        errors at runtime, all the errors of "Typed18N" will be reported at compilation-time
        (This functionality requires the compilation-time byte-code instrument).


      • 1.1.2. Delegate


        Better way to support event nodification, like the delegate of .NET Framework.
        It's more simple, More economical and more powerful than the suggestion of Java Bean Standard
        (This functionality requires the compilation-time byte-code instrument).


      • 1.1.3. Equality


        The developers often override the method "public boolean equals(Object o)",
        they often have two choices to check whether type of argument is same with the current object(this):

        • Too strict way: if (this.getClass() != o.getClass()) return false;

        • Too lax way: if (!(o instanceof ${ThisClass})) return false;


        Unfortunately, Both of them are wrong, this functionality gives a perfect solution,
        its corresponding demos indicate their problems and give the correct solution.


      • 1.1.4. Graph Traveler


        This functionality is used to visit a object graph by depth first way or breadth first way,
        during the visiting, it supports many context variables.




    • 1.2. BabyFish Collection Framework




      • 1.2.1. X Collection Framework



        "X" means "eXtensible", X Collection Framework extends the interfaces of Java Collection Framework and gives a new implementation to support some incredible functionalities.



        Here we only disuccss two most important functionalities of X Collection Framework
        (Please see demo-guide to know all functionalities).




        • 1.2.1.1. Bidi Collection

          Like "org.apache.commons.collections4.BidiMap",
          X Collection Framework support BidiMap to let "java.util.Map" supports unique constraint of value(not key);
          In a similar way, BidiList is supported too.


        • 1.2.1.2. Unstable Collection Elements


          Java Framework supports hash structure and red black tree via HashSet, HashMap, TreeSet and TreeMap,
          their benefit is high peformance but defect is an object cannot be changed since
          it has been added into collections as Set element or Map key.



          X Collection Framework supports "Unstable Collection Elements", an object can still be changed
          even if it has been added into Set as element added into Map as key, because all the sets and maps will be adjusted automatically when this object is changed.




          Collection
          Materialize of "Unstable Collection Elements"




          Set
          Unstable elements


          Map
          Unstable keys


          BidiList
          Unstable elements


          BidiMap
          Unstable keys


          Unstable values









      • 1.2.2. MA Collection Framework



        "MA" means "Modification Aware", MA Collection Framework extends X Collection Framework to support the modification event nodification.
        For each modified element or key-value pair, a couple of events will be triggered,
        one is triggered before the modification and the other one is triggered after the modification.
        This functionality looks like the row level trigger of RDMBS very much.



        Here we only disuccss two most important functionalities of MA Collection Framework
        (Please see demo-guide to know all functionalities).




        • 1.2.2.1 Implicit Event

          For BabyFish Collection Framework, not only the explicit collection modification API invocation can change the data of collection object,
          but also the collection object can be modified by the system automatically.
          The most typical representative is automatic collection adjusting caused by "Unstable Collection Elements".
          Events can still be triggered by the modification that isn't caused by developer and is automatic, implicit.


        • 1.2.2.2 Bubble Event


          Java Colletion Framework support collection views, for example:



          • "java.util.NavigableMap" supports methods headMap, tailMap, subMap and descendingMap.

          • "java.util.NavigableSet" supports methods headSet, tailSet, subSet, descendingSet and descendingIterator.

          • "java.util.List" supports methods subList and listIterator.

          • "java.util.Map" supports keySet, methods values and entrySet.

          • "java.util.Collection" supports method iterator.


          that means the developer can create new collection view from original collection or collection view,
          all the collection views share the same data with the root collection,
          the root collection will be affected when any one view is changed.


          MA Collection Framework supports "Bubble Event", when the collection view is changed by the developer, the event will be triggered by the view itself; then the event will be bubbled to its parent view, then a new event will be triggered by the parent view. By parity of reasoning, finally, the event will bubbled to root and new event will be triggered by original collection.







      • 1.2.3. Lazy Collection Framework



        As we know, ORM frameworks often support a technology called "Lazy Loading". Lazy collection is fake collection without data, it can become the real collection by IO reading when it's used by developer at first time.
        This functionality is very powerful, it's very wasteful if it can only be used by ORM frameworks.



        In order to let this powerful functionality can be used anywhere(Not only by ORM implementation), babyfish support Lazy Collection Framework which is abstract and universal.



        No demo for it, it's not API of babyfish, it's SPI of babyfish.




      • 1.2.4. Collection Utils



        Java Collection Framework has very powerful tool class "java.util.Collections", this class supports many static methods to create magical collection proxies.



        BabyFish Collection Framework extends the interfaces of Java Collection Framework, similarly, it must support its own tool class too: "org.babyfish.collection.MACollections".






    • 1.3. ObjectModel4Java



      ObjectModel is the core functionality of BabyFish, it the reason why I created this framework.



      ObjectModel is used to support "Smart Data Structcure", it can be splitted to two parts




      • ObjectModel4Java: Smart data structure for java language, this is being discussed by this chapter.


      • ObjectModel4JPA: Smart data structure for JPA entity classes, this will be discussed by next chapter.




      ObjectModel4Java has many functionalities, this document only introduces two of them: 1, Consistency of bidirectional association; 2, Unstable objects.
      (Please see demo-guide to know all functionalities).


      1.3.1. Consistency of bidirectional association



      Java developers often declare the data classes without any logic except getters and setters
      (Bluntly, they're C-structures), the data structure described by these simple classes
      does not have enough conveniences and intelligent.
      For a simple example, there is a bidirectional association between
      two objects, when one side of that association is modified by the developer,
      the other side won't be changed, so the data structure become inconsistent,
      we can navigate to object B from object A, but cannot navigate to object A from object B.



      ObjectModel4Java adds the intelligent into data structure,
      but it does not increase the code complexity, after all,
      the classes without any logic except getters and setters is so easy to be developed that
      they are accepted by every one. ObjectModel4Java only requires the developers to add a little
      annotations to those simple classes, after the compilation-time bytecode instrument,
      they will become powerful data classes.



      Let's see an example, declare the bidirectional association between department and employees.




      • One department has many employees.
        @Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
        
        public class Department {

        //One side of bidirectional association,
        //this field is the mirroring of "Employee.department".
        @Association(opposite = "department")
        private List<Employee> employees; //List has order.

        The getters and setters are omitted
        }



      • Each employee belongs to a department, and it also know its position in the list of its department.
        @Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
        
        public class Employee {

        //Other side of bidirectional association,
        //this field is the mirroring of "Department.employees".
        @Association(opposite = "employees")
        private Department department; //Employee belongs to a department, if not, it's null

        // This field is attached to "Employee.department", it's the index of current object in list of
        // parent department object. If this object does not belong to any department object, it's -1.
        @IndexOf("department")
        private int index;

        The getters and setters are omitted
        }






      Now, there are 6 objects, their variable names are department1, department2, employee1, employe2, employee3 and employee4, this is the data stucure:





      Department object
      Employee object


      Variable name
      employees
      Variable name
      department
      index




      department1
      [ employee1, employee2 ]
      employee1
      department1
      0


      employee2
      department1
      1


      department2
      [ employee3, employee4 ]
      employee3
      department2
      0


      employee4
      department2
      1




      Then the developer modifies the "employees" collection of "department1", like this


      department1.getEmployees().add(0, employee3);

      This code inserts the "employee3" into the head of "department1.employees",
      In order to preserve the consistency of data strucure, ObjectModel4Java will do these works:


      • Remove "employee3" from the collection "department2.employees" automatically.

      • Assign the "employee3.department" to be "department1" automatically.

      • Increase "employee1.index" automatically, from 0 to 1.

      • Increase "employee2.index" automatically, from 1 to 2.

      • Decrease "employee4.index" automatically, from 1 to 0.


      Finally, the data structure become:





      Department Object
      Employee Object


      Variable name
      employees
      Variable name
      department
      index




      department1
      [ employee3, employee1, employee2 ]
      employee1
      department1
      1


      employee2
      department1
      2


      employee3
      department1
      0


      department2
      [ employee4 ]
      employee4
      department2
      0





    • 1.3.2. Unstable Objects.



      In previous demo, the collection field uses "java.util.List", of course, "java.util.Set" and "java.util.Map"
      can be used too. In this demo, we use "java.util.Set" to decribe the bidirectional many-to-many
      association between companies and investors.




      • A company can be jointly funded by multiple investors.
        @Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
        
        public class Company {

        @Scalar //Scalar, not association.
        private String shortName;

        @Association(opposite = "companies")
        // The annotation "@ComparatorRule" means this set collection uses the field "Investor.name"
        // to calculate the hashCode of investor and check whether two investors are equal.
        @ComparatorRule(properties = @ComparatorProperty("name"))
        private Set<Investor> investors;

        The getters and setters are omitted
        }




      • An investor can invest in multiple companies.
        @Model //Uses ObjectModel4Java, requires compilation-time bytecode instrument.
        
        public class Investor {

        @Scalar //Scalar, not association.
        private String name;

        @Association(opposite = "investors")
        private Set<Company> companies;

        The getters and setters are omitted
        }





      Now there are 3 object; one of them is an "Company" object whose variable name is "apple",
      the other two are "Investor" objects whose variable name are "steve" and "sulley".
      The data structure is:





      Company object
      Investor object


      Variable name
      shortName
      investors
      Variable name
      name
      companies




      apple
      Apple
      [ steve, sculley ]
      steve
      Steve
      [ apple ]


      sculley
      Sculley
      [ apple ]



      Now, the develop execute this code:


      sculley.setName("Steve");


      After execute this code, The value of "sculley.name" will be same with the value of "steve.name", both of them are "Steve";
      But the collection field investors" of "Company"
      uses the annotation@ComparatorRule
      to let this collection cannot contains tow Investor objects with the same name.
      This is a paradoxical situation.



      Fortunately, the field investors" of "Company"
      supports "Unstable Collection Elements"; that will cause the following effects.




      • In order to preserve the unique contraint of the set field,
        the object "steve" will be crowded out from the collection
        investors of object "apple"
        automatically because of
        "Unstable Collection Elements".


      • the object "steve" is longer the investor of "apple",
        in order to preserve the consistency of bidirectional assocation.
        the objet "apple" will be removed from the collection
        companies of object "steve" auotmatically.


      Finally, the data structure become:





      Company object
      Investor object


      Variable name
      shortName
      investors
      Variable name
      name
      companies




      apple
      Apple
      [ sculley ]
      steve
      Steve
      []



      sculley
      Steve
      [ apple ]







  • 2. JPA Functionalities




    • 2.1. ObjectModel4JPA



      ObjectModel4JPA is an enhancement of ObjectModel4Java,
      it has the same functionalities with ObjectModel4Java,
      but their objectives are not same, it allows the JPA entity classes to use the ObjectMode,
      not for the ordinary java classes; their declaration modes are different too,
      please see demo-guide to know more details.



      Be same with ObjectModel4Java
      ObjectModel4JPA requires the compilation-time bytecode instrument of Maven plugin too.




    • 2.2. BabyFish Hibernate Collection Framework




      • In ObjectModel4Java
        The collections used by the association field can preserve the consistency of bidirectional assocation,
        of course, they has the all the functionalities of X Collection Framework and MA Collection Framework too.
        ObjectModel4JPA has the same functionalities with ObjectModel4Java
        The its collections must have those functionalities too.


      • ObjectModel4JPA is designed for JPA/Hibernate,
        so its collections must support the the functionality "Lazy Loadding",
        like the protogenous JPA/Hibernate.



      In order to let the collections of ObjectModel support all of those functionalities,
      BabyFish support its own Hibernate Collection Framework by extending Lazy Collection Framework.



      No demo for it because it's an internal module of babyfish-hibernate-extension.
      The developer only need to know that the collections of ObjectModel4JPA have both
      the functionalities of ObjectModel4Java's collections and
      the functionaltities of Hibernate's collections.




    • 2.3. JPA & Hibernate Extension



      In order to add some new functionalities, BabyFish extends the API of JPA and Hibernate.
      This deocument only introduces two of them: QueryPath and Oracle Optimization
      (Please see demo-guide to know all functionalities).




      • 2.3.1. Query Path



        In order to support "dynamic eager fetching"(
        Association fetches is specified by the arguments of UI or business logic layer, not by the hard code in the data accessing layer),
        BabyFish supports "Query Path", it looks like these technologies


        very much.
        This functionality is more simpler, more beautiful and more powerful than

        javax.persistence.EntityGraph

        which is provided since JPA2.1, please forget it and use Query Path in practical projects.


        Comparing with
        Including functionality of Active Record
        or
        Including functionality of ADO.NET Entity Framework,
        The Query Path has 3 advantages.




        • In Active Record or ADO.NET Entity Framework, Include Paths are string which isn't type-safe,
          the errors of Include Paths won't reported until run or test the application;
          In BabyFish, Query Paths are created by the "Query Path meta-model" whose source code is automatically generated at compilation-time by maven plugin,
          the errors of Query Paths will be reported as compilation error.


        • Not only the object associations graph with unlimited depth and breadth can be fetched dynamically, but also the lazy scalar field(Not not always but often is lob field) can be fetched dynamically.


        • It can also be used to sort the objects of query result and sort associations collections.




      • 2.3.2. Oracle Optimization



        Hibernate has a performance issue: When the query has both collection fetches and paging filter,
        Hibernate cannot generate paging restriction in SQL statement,
        all the matched rows will be selected and the paging filter will be applied in memory.
        This is a big problem so Hibernate writes this line in log file:


        "firstResult/maxResults specified with collection fetch; applying in memory!"



        BabyFish can resolve this problem when the database is Oracle, please uses the dialect provided by BabyFish, such as:









# license: LPGL3.0
BabyFish uses the LGPL-3.0 license so that it can be used in commercial projects,
please see [http://opensource.org/licenses/LGPL-3.0](http://opensource.org/licenses/LGPL-3.0) to know more.

# Thanks
Thank two great frameworks: [ASM](http://asm.ow2.org) and [ANTLR](http://www.antlr.org)

# History
>* Aug 2008: I have some ideas, I decided to create an open source framework by using all of my spare time.
>* Oct 2015: This first version 1.0.0.Alpha is finished, and it's published on github.
>* Jun 2016: The version 1.1.0 is finished.

# Contact me, give suggestions and expectations
Tao Chen, [babyfish-ct@163.com](mailto:babyfish-ct@163.com)

2016-06-25, ChengDu, China