gigadot avatar gigadot committed 27fe2fd

added mechanism to set @XmlTransient at runtime using @XMLTransientRules

Comments (0)

Files changed (13)

model/src/main/java/gigadot/chom/model/brownie/Address.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package gigadot.chom.model.brownie;
-
-/**
- *
- * @author wp214
- */
-public class Address {
-
-    private String street;
-
-    public String getStreet() {
-        return street;
-    }
-
-    public void setStreet(String street) {
-        this.street = street;
-    }
-}

model/src/main/java/gigadot/chom/model/brownie/Customer.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package gigadot.chom.model.brownie;
-
-import java.util.HashMap;
-import java.util.Map;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods;
-
-/**
- *
- * @author wp214
- */
-@XmlRootElement
-@XmlType(propOrder = {"firstName", "lastName", "address"})
-@XmlVirtualAccessMethods
-public class Customer {
-
-    private String firstNameX;
-    private String lastName;
-    private Address billingAddress;
-
-    public String getFirstName() {
-        return firstNameX;
-    }
-
-    public void setFirstName(String firstName) {
-        this.firstNameX = firstName;
-    }
-
-    public String getLastName() {
-        return lastName;
-    }
-
-    public void setLastName(String lastName) {
-        this.lastName = lastName;
-    }
-
-    public Address getBillingAddress() {
-        return billingAddress;
-    }
-
-    public void setBillingAddress(Address billingAddress) {
-        this.billingAddress = billingAddress;
-    }
-
-}

model/src/main/java/gigadot/chom/model/internal/jaxb/ReflectionUtils.java

-package gigadot.chom.model.internal.jaxb;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- *
- * @author Weerapong
- */
-class ReflectionUtils {
-
-    public static Field[] getAnnotatedDeclaredFields(Class clz, Class<? extends Annotation>... annotationClasses) {
-        Set<Field> fds = new HashSet<Field>(Arrays.asList(clz.getDeclaredFields()));
-        for (Iterator<Field> it = fds.iterator(); it.hasNext();) {
-            Field field = it.next();
-            // check for given annotations. if a method does not have all the annotation classes
-            // we remove the method from the set. whatever left are what we want.
-            for (Class<? extends Annotation> annoClz : annotationClasses) {
-                if (!field.isAnnotationPresent(annoClz)) {
-                    it.remove();
-                    break;
-                }
-            }
-        }
-        return fds.toArray(new Field[fds.size()]);
-    }
-
-    public static Field[] getFields(Class clz) {
-        Set<Field> fds = new HashSet<Field>();
-        fds.addAll(Arrays.asList(clz.getDeclaredFields()));
-        fds.addAll(Arrays.asList(clz.getFields()));
-        fds.removeAll(Arrays.asList(Object.class.getFields()));
-        return fds.toArray(new Field[fds.size()]);
-    }
-    /**
-     * get only one annotated method. the returning method is not guaranteed to be the first method in the declaration
-     * order. only use this if you are sure that you have only one annotated method per class. null is return if nothing
-     * found
-     *
-     * @param clz
-     * @param annotationClasses
-     * @return
-     */
-    public static Method getAnnotatedMethod(Class clz, Class<? extends Annotation>... annotationClasses) {
-        Method[] annotatedMethods = getAnnotatedMethods(clz, annotationClasses);
-        if (annotatedMethods.length > 0) {
-            return annotatedMethods[0];
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * get all declared methods including the inherited public methods
-     * (except those from Object class) that are annotated with a given annotation
-     * @param clz
-     * @param annotationClasses
-     * @return
-     */
-    public static Method[] getAnnotatedMethods(Class clz, Class<? extends Annotation>... annotationClasses) {
-        Set<Method> mt = new HashSet<Method>(Arrays.asList(getMethods(clz)));
-        for (Iterator<Method> it = mt.iterator(); it.hasNext();) {
-            Method method = it.next();
-            // check for given annotations. if a method does not have all the annotation classes
-            // we remove the method from the set. whatever left are what we want.
-            for (Class<? extends Annotation> annoClz : annotationClasses) {
-                if (!method.isAnnotationPresent(annoClz)) {
-                    it.remove();
-                    break;
-                }
-            }
-        }
-        return mt.toArray(new Method[mt.size()]);
-    }
-
-    /**
-     * get all declared methods including the inherited public methods
-     * except those from Object class
-     * @param clz
-     * @return
-     */
-    public static Method[] getMethods(Class clz) {
-        Set<Method> mt = new HashSet<Method>();
-        // add declared methods first
-        mt.addAll(Arrays.asList(clz.getDeclaredMethods()));
-        // add method and its inhertited methods later in case that they are inaccessible.
-        mt.addAll(Arrays.asList(clz.getMethods()));
-        mt.removeAll(Arrays.asList(Object.class.getMethods()));
-        return mt.toArray(new Method[mt.size()]);
-    }
-
-    public static boolean isGetter(Method method) {
-        return method.getName().startsWith("get") && method.getParameterTypes().length == 0;
-    }
-
-    public static boolean isSetter(Method method) {
-        // is a setter if begin with set and its getter return the same type as its parameter
-        return method.getName().startsWith("set") && method.getParameterTypes().length == 1;
-    }
-
-    public static String getSetterName(Method method) {
-        if (isSetter(method)) {
-            return method.getName();
-        } else if (isGetter(method)) {
-            return "set" + method.getName().substring(3);
-        } else {
-            return null;
-        }
-    }
-
-    public static String getGetterName(Method method) {
-        if (isGetter(method)) {
-            return method.getName();
-        } else if (isSetter(method)) {
-            return "get" + method.getName().substring(3);
-        } else {
-            return null;
-        }
-    }
-
-    public static Method getGetter(Method method) {
-        try {
-            String getterName = getGetterName(method);
-            return method.getDeclaringClass().getMethod(getterName);
-        } catch (Exception ex) {
-            return null;
-        }
-    }
-
-    public static Method getSetter(Method method) {
-        try {
-            String setterName = getSetterName(method);
-            Method getter = getGetter(method);
-            return method.getDeclaringClass().getMethod(setterName, getter.getReturnType());
-        } catch (Exception ex) {
-            return null;
-        }
-    }
-}

model/src/main/java/gigadot/chom/model/internal/jaxb/XmlBinderScanner.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package gigadot.chom.model.internal.jaxb;
-
-import gigadot.rebound.Rebound;
-import java.util.Set;
-
-/**
- *
- * @author wp214
- */
-public class XmlBinderScanner {
-    //setRules
-    public void method() {
-        Rebound r = new Rebound("gigadot.chom.model", true, false);
-        Set<Class<? extends Object>> clzzes = r.getSubClassesOf(Object.class);
-        for (Class<? extends Object> clz : clzzes) {
-            // find @XmlTransientRules
-            
-            // get the method or property name
-            // apply transient using my metadatasource
-        }
-    }
-
-}

model/src/main/java/gigadot/chom/model/internal/jaxb/package-info.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
 @XmlSchema(
 xmlns = {
     @XmlNs(prefix = "", namespaceURI = MolDocNamespaceConstants.MOLDOC),
 elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
 attributeFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED)
 
+/**
+ * Provide implementation for internal use only (within this module). Using classes from this package is usually not needed and may cause
+ * undesirable behaviour.
+ */
 package gigadot.chom.model.internal.jaxb;
 
 import gigadot.chom.model.util.MolDocNamespaceConstants;

model/src/main/java/gigadot/chom/model/jaxb/ReflectionUtils.java

+package gigadot.chom.model.jaxb;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ *
+ * @author Weerapong
+ */
+class ReflectionUtils {
+
+    public static Field[] getAnnotatedDeclaredFields(Class clz, Class<? extends Annotation>... annotationClasses) {
+        Set<Field> fds = new HashSet<Field>(Arrays.asList(clz.getDeclaredFields()));
+        for (Iterator<Field> it = fds.iterator(); it.hasNext();) {
+            Field field = it.next();
+            // check for given annotations. if a method does not have all the annotation classes
+            // we remove the method from the set. whatever left are what we want.
+            for (Class<? extends Annotation> annoClz : annotationClasses) {
+                if (!field.isAnnotationPresent(annoClz)) {
+                    it.remove();
+                    break;
+                }
+            }
+        }
+        return fds.toArray(new Field[fds.size()]);
+    }
+
+    public static Field[] getFields(Class clz) {
+        Set<Field> fds = new HashSet<Field>();
+        fds.addAll(Arrays.asList(clz.getDeclaredFields()));
+        fds.addAll(Arrays.asList(clz.getFields()));
+        fds.removeAll(Arrays.asList(Object.class.getFields()));
+        return fds.toArray(new Field[fds.size()]);
+    }
+    /**
+     * get only one annotated method. the returning method is not guaranteed to be the first method in the declaration
+     * order. only use this if you are sure that you have only one annotated method per class. null is return if nothing
+     * found
+     *
+     * @param clz
+     * @param annotationClasses
+     * @return
+     */
+    public static Method getAnnotatedDeclaredMethod(Class clz, Class<? extends Annotation>... annotationClasses) {
+        Method[] annotatedMethods = getAnnotatedDeclaredMethods(clz, annotationClasses);
+        if (annotatedMethods.length > 0) {
+            return annotatedMethods[0];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * get all declared methods
+     * (except those from Object class) that are annotated with a given annotation
+     * @param clz
+     * @param annotationClasses
+     * @return
+     */
+    public static Method[] getAnnotatedDeclaredMethods(Class clz, Class<? extends Annotation>... annotationClasses) {
+        Set<Method> mt = new HashSet<Method>(Arrays.asList(getDeclaredMethods(clz)));
+        for (Iterator<Method> it = mt.iterator(); it.hasNext();) {
+            Method method = it.next();
+            // check for given annotations. if a method does not have all the annotation classes
+            // we remove the method from the set. whatever left are what we want.
+            for (Class<? extends Annotation> annoClz : annotationClasses) {
+                if (!method.isAnnotationPresent(annoClz)) {
+                    it.remove();
+                    break;
+                }
+            }
+        }
+        return mt.toArray(new Method[mt.size()]);
+    }
+
+    /**
+     * get all declared methods
+     * except those from Object class
+     * @param clz
+     * @return
+     */
+    public static Method[] getDeclaredMethods(Class clz) {
+        Set<Method> mt = new HashSet<Method>();
+        // add declared methods first
+        mt.addAll(Arrays.asList(clz.getDeclaredMethods()));
+        mt.removeAll(Arrays.asList(Object.class.getMethods()));
+        return mt.toArray(new Method[mt.size()]);
+    }
+
+    public static boolean isGetter(Method method) {
+        return method.getName().startsWith("get") && method.getParameterTypes().length == 0;
+    }
+
+    public static boolean isSetter(Method method) {
+        // is a setter if begin with set and its getter return the same type as its parameter
+        return method.getName().startsWith("set") && method.getParameterTypes().length == 1;
+    }
+
+    public static String getSetterName(Method method) {
+        if (isSetter(method)) {
+            return method.getName();
+        } else if (isGetter(method)) {
+            return "set" + method.getName().substring(3);
+        } else {
+            return null;
+        }
+    }
+
+    public static String getGetterName(Method method) {
+        if (isGetter(method)) {
+            return method.getName();
+        } else if (isSetter(method)) {
+            return "get" + method.getName().substring(3);
+        } else {
+            return null;
+        }
+    }
+
+    private static String lowerCaseFirstChar(String name) {
+        return Character.toLowerCase(name.charAt(0)) + name.substring(1);
+    }
+
+    public static String getPropertyName(Method method) {
+        if (isGetter(method)) {
+            if (getSetter(method) != null) {
+                return lowerCaseFirstChar(method.getName().substring(3));
+            } else {
+                throw new IllegalArgumentException(method + " has no setter counterpart.");
+            }
+        } else if (isSetter(method)) {
+            if (getGetter(method) != null) {
+                return lowerCaseFirstChar(method.getName().substring(3));
+            } else {
+                throw new IllegalArgumentException(method + " has no getter counterpart.");
+            }
+        } else {
+            throw new IllegalArgumentException(method + " is neiter getter or setter.");
+        }
+    }
+
+    public static Method getGetter(Method method) {
+        try {
+            String getterName = getGetterName(method);
+            return method.getDeclaringClass().getMethod(getterName);
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+
+    public static Method getSetter(Method method) {
+        try {
+            String setterName = getSetterName(method);
+            Method getter = getGetter(method);
+            return method.getDeclaringClass().getMethod(setterName, getter.getReturnType());
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+}

model/src/main/java/gigadot/chom/model/jaxb/XmlBinderScanner.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package gigadot.chom.model.jaxb;
+
+import gigadot.chom.model.internal.jaxb.MultiPackageMetadataSourceFactory;
+import gigadot.chom.model.jaxb.XmlTransientRules;
+import gigadot.rebound.Rebound;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.eclipse.persistence.jaxb.metadata.MetadataSource;
+
+/**
+ *
+ * @author wp214
+ */
+public class XmlBinderScanner {
+
+    private Set<String> rules = new HashSet<String>();
+    private MultiPackageMetadataSourceFactory mpmsf = null;
+
+    public void setRules(String... rules) {
+        //this.rules = rules;
+        this.rules.clear();
+        this.rules.addAll(Arrays.asList(rules));
+    }
+
+    public Map<String, MetadataSource> getXmlTransientRulesMetadataSourceMap() {
+        if (mpmsf == null) {
+            init();
+        }
+        return mpmsf.getMetadataSources();
+    }
+
+    private void init() {
+        Rebound r = new Rebound("gigadot.chom.model", true, false);
+        Set<Class<? extends Object>> clzzes = r.getSubClassesOf(Object.class);
+        mpmsf = new MultiPackageMetadataSourceFactory();
+        for (Class<? extends Object> clz : clzzes) {
+            // find @XmlTransientRules
+            Method[] transientMethods = ReflectionUtils.getAnnotatedDeclaredMethods(clz, XmlTransientRules.class);
+            for (Method method : transientMethods) {
+                // get the method or property name
+                String propertyName = ReflectionUtils.getPropertyName(method);
+                // get rules
+                XmlTransientRules xmlTransientRules = method.getAnnotation(XmlTransientRules.class);
+                boolean shouldApplyTransient = false;
+                for (String rule : xmlTransientRules.value()) {
+                    if (rules.contains(rule)) {
+                        shouldApplyTransient = true;
+                        break;
+                    }
+                }
+                if (shouldApplyTransient) {
+                    // apply transient using my metadatasource
+                    mpmsf.setXmlTransient(clz, propertyName);
+                }
+            }
+
+        }
+    }
+}

model/src/main/java/gigadot/chom/model/jaxb/XmlTransientRules.java

 import java.lang.annotation.Target;
 
 /**
- * override jaxb annotation. if field is annotated and rule is enforced, the field will be set to transient. if field is
- * annotated with transient, it will not be overridden.
+ * override jaxb annotation. if getter is annotated and rule is enforced, the getter will be set to transient. if the getter is
+ * annotated with @XmlTransient, @XmlTransient is prioritised.
  * @author wp214
  */
 @Target({ElementType.METHOD})

model/src/test/java/gigadot/chom/model/brownie/Address.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package gigadot.chom.model.brownie;
+
+/**
+ *
+ * @author wp214
+ */
+public class Address {
+
+    private String street;
+
+    public String getStreet() {
+        return street;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+}

model/src/test/java/gigadot/chom/model/brownie/Customer.java

+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package gigadot.chom.model.brownie;
+
+import gigadot.chom.model.jaxb.XmlTransientRules;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods;
+
+/**
+ *
+ * @author wp214
+ */
+@XmlRootElement
+@XmlType(propOrder = {"firstName", "lastName", "address"})
+@XmlVirtualAccessMethods
+public class Customer {
+
+    private String firstNameX;
+    private String lastName;
+    private Address billingAddress;
+
+    @XmlTransientRules({"normal"})
+    public String getFirstName() {
+        return firstNameX;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstNameX = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public Address getBillingAddress() {
+        return billingAddress;
+    }
+
+    public void setBillingAddress(Address billingAddress) {
+        this.billingAddress = billingAddress;
+    }
+
+}

model/src/test/java/gigadot/chom/model/brownie/SomeTest.java

  */
 package gigadot.chom.model.brownie;
 
-import gigadot.chom.model.internal.jaxb.MultiPackageMetadataSourceFactory;
+import gigadot.chom.model.jaxb.XmlBinderScanner;
 import java.util.HashMap;
 import java.util.Map;
 import javax.xml.bind.JAXBContext;
 public class SomeTest {
 
     @Test
-    public void methodExtensions() throws JAXBException {
+    public void xmlTransientRulesExtension() throws JAXBException {
+        XmlBinderScanner xmlBinderScanner = new XmlBinderScanner();
+        xmlBinderScanner.setRules("normal");
         Map<String, Object> properties = new HashMap<String, Object>();
-        MultiPackageMetadataSourceFactory mpmsf = new MultiPackageMetadataSourceFactory();
-        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, mpmsf.getMetadataSources());
+        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, xmlBinderScanner.getXmlTransientRulesMetadataSourceMap());
 
         JAXBContext jc = JAXBContext.newInstance(new Class[]{Customer.class}, properties);
         Marshaller marshaller = jc.createMarshaller();
 
         marshaller.marshal(customer, System.out);
 
-        mpmsf.setXmlTransient(Customer.class, "firstName");
-        mpmsf.setXmlTransient(Customer.class, "lastName");
         JAXBHelper.getJAXBContext(jc).refreshMetadata();
 
         marshaller.marshal(customer, System.out);
     }
-
 }

model/src/test/java/gigadot/chom/model/internal/jaxb/XmlBinderScannerTest.java

-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package gigadot.chom.model.internal.jaxb;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author wp214
- */
-public class XmlBinderScannerTest {
-
-    /**
-     * Test of method method, of class XmlBinderScanner.
-     */
-    @Test
-    public void testMethod() {
-        System.out.println("method");
-        XmlBinderScanner instance = new XmlBinderScanner();
-        instance.method();
-    }
-}
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-compiler-plugin</artifactId>
                     <configuration>
-                        <source>1.7</source>
-                        <target>1.7</target>
+                        <source>1.6</source>
+                        <target>1.6</target>
                         <encoding>${project.build.sourceEncoding}</encoding>
                     </configuration>
                 </plugin>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.