001package com.basilv.examples.java5;
002
003import java.lang.reflect.Array;
004import java.util.*;
005
006
007class BusinessEntity {
008  private Integer id;
009
010  public BusinessEntity(Integer id) {
011    this.id = id;
012  }
013  
014  public Integer getId() {
015    return id;
016  }
017
018  public int getIdAsPrimitiveInt() {
019    return id; // Unboxing (Integer to int). What happens if id is null???
020  }
021
022  @Override // Annotation (Java standard) 
023  public String toString() {
024    return "Id:" + id;
025  }
026  
027  public BusinessEntity getMyself() {
028    return this;
029  }
030  
031  
032}
033
034class PersonEntity extends BusinessEntity {
035
036  // Enumerated Type (enum)
037  // Can get list of values with AddressType.values();
038  // Can get particular instance with AddressType.valueOf("Mailing");
039  // Can even have abstract methods that particular enumerated value constant overrides.
040  public enum AddressType {
041    MAILING("Mailing", 1),
042    BILLING("Billing", 2);
043    
044    private String displayName;
045    
046    // Annotation (warning type Eclipse-specific)
047    @SuppressWarnings("unused")  
048    private int id;
049    
050    private AddressType(String displayName, int id) {
051        this.displayName = displayName;
052        this.id = id;
053    }
054
055    public String getDisplayName() {
056      return displayName;
057    }
058
059  }
060  
061  public PersonEntity(Integer id) {
062    super(id);
063  }
064
065  private AddressType addressType;
066
067  public AddressType getAddressType() {
068    return addressType;
069  }
070  public void setAddressType(AddressType addressType) {
071    this.addressType = addressType;
072  }
073
074  @Override 
075  // Covariant return - note return type of method in parent class.
076  public PersonEntity getMyself() { 
077    return this;
078  }
079
080}
081
082// Generic type definition.
083// This can get more complex with the use of wildcards.
084abstract class BusinessService<T extends BusinessEntity> {
085  public abstract List<T> findAll();
086  
087  public abstract T loadByPrimaryKey(Long id);
088  
089  
090  // Static generic method
091  public static <T> T[] toArray(List<T> list, Class<T> clazz) {
092    // This construct is not allowed because the specific type of the generic
093    // is not kept at runtime - this is called erasure.
094    // T[] array = new T[]();
095
096    // Instead, pass in the class as a 'Type Token'
097    // Note that the class Class is itself genericized.
098    
099    @SuppressWarnings("unchecked") // Annotation - needed for cast. 
100    T[] array = (T[]) Array.newInstance(clazz, 0);
101    return list.toArray(array);
102  }
103}
104
105// Instantiation of a generic type
106public class PersonServiceImpl extends BusinessService<PersonEntity> {
107
108  @Override
109  @Deprecated // Annotation (Java standard)
110  public List<PersonEntity> findAll() {
111    // Using a list from the collections API
112    List<PersonEntity> list = new ArrayList<PersonEntity>();
113    list.add(new PersonEntity(123)); // Autoboxing (int to Integer)
114    return list;
115  }
116  
117  @Override public PersonEntity loadByPrimaryKey(Long id) {
118    List<PersonEntity> personList = findAll();
119    for (PersonEntity person : personList) { // Enhanced for loop over list.
120      if (person.getId().equals(id)) {
121        return person;
122      }
123    }
124    
125    PersonEntity[] backupArray = {
126      new PersonEntity(1),
127      new PersonEntity(2),
128    };
129    
130    for (PersonEntity person : backupArray) { // Enhanced for loop over array
131      if (person.getId().equals(id)) {
132        return person;
133      }
134    }
135    
136    return null;
137  }
138  
139  // Use of generic wildcard.
140  // Use of Varargs (variable arguments)
141  public Map<Integer,? extends PersonEntity> collectIntoMap(PersonEntity... people) {
142    // Using a map from the collections API
143    Map<Integer, PersonEntity> map = new HashMap<Integer,PersonEntity>();
144    for (PersonEntity person : people) {
145      map.put(person.getId(), person);
146    }
147    return map;
148  }
149  
150}
151
152// Other notes:
153// - You can define your own annotations. Used mostly by frameworks (i.e. EJB 3)