http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/Visibility.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/Visibility.java b/org.apache.juneau/src/main/java/org/apache/juneau/Visibility.java new file mode 100644 index 0000000..03a927f --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/Visibility.java @@ -0,0 +1,199 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau; + +import java.lang.reflect.*; + +/** + * Defines class/field/method visibilities. + * <p> + * Used to specify minimum levels of visibility when detecting bean classes, methods, and fields. + * Used in conjunction with the following bean context properties: + * <ul> + * <li>{@link BeanContext#BEAN_beanConstructorVisibility} + * <li>{@link BeanContext#BEAN_beanClassVisibility} + * <li>{@link BeanContext#BEAN_beanFieldVisibility} + * <li>{@link BeanContext#BEAN_methodVisibility} + * </ul> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public enum Visibility { + + /** Ignore all */ + NONE, + + /** Include only <jk>public</jk> classes/fields/methods. */ + PUBLIC, + + /** Include only <jk>public</jk> or <jk>protected</jk> classes/fields/methods. */ + PROTECTED, + + /** Include all but <jk>private</jk> classes/fields/methods. */ + DEFAULT, + + /** Include all classes/fields/methods. */ + PRIVATE; + + /** + * Identifies if the specified mod matches this visibility. + * Example: + * <code> + * <jsf>PUBLIC</jsf>.isVisible(MyPublicClass.<jk>class</jk>.getModifiers()); <jc>//true</jk> + * <jsf>PUBLIC</jsf>.isVisible(MyPrivateClass.<jk>class</jk>.getModifiers()); <jc>//false</jk> + * <jsf>PRIVATE</jsf>.isVisible(MyPrivateClass.<jk>class</jk>.getModifiers()); <jc>//true</jk> + * <jsf>NONE</jsf>.isVisible(MyPublicClass.<jk>class</jk>.getModifiers()); <jc>//false</jk> + * </code> + * + * @param mod The modifier from the object being tested (e.g. results from {@link Class#getModifiers()}. + * @return <jk>true</jk> if this visibility matches the specified modifier attribute. + */ + public boolean isVisible(int mod) { + switch(this) { + case NONE: return false; + case PRIVATE: return true; + case DEFAULT: return ! Modifier.isPrivate(mod); + case PROTECTED: return Modifier.isProtected(mod) || Modifier.isPublic(mod); + default: return Modifier.isPublic(mod); + } + } + + /** + * Shortcut for <code>isVisible(x.getModifiers());</code> + * + * @param x The constructor to check. + * @return <jk>true</jk> if the constructor is at least as visible as this object. + */ + public boolean isVisible(Constructor<?> x) { + return isVisible(x.getModifiers()); + } + + /** + * Shortcut for <code>isVisible(x.getModifiers());</code> + * + * @param x The method to check. + * @return <jk>true</jk> if the method is at least as visible as this object. + */ + public boolean isVisible(Method x) { + return isVisible(x.getModifiers()); + } + + /** + * Shortcut for <code>isVisible(x.getModifiers());</code> + * + * @param x The field to check. + * @return <jk>true</jk> if the field is at least as visible as this object. + */ + public boolean isVisible(Field x) { + return isVisible(x.getModifiers()); + } + + /** + * Makes constructor accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't. + * Security exceptions thrown on the call to {@link Constructor#setAccessible(boolean)} are quietly ignored. + * + * @param x The constructor. + * @return The same constructor if visibility requirements met, or <jk>null</jk> if visibility requirement not + * met or call to {@link Constructor#setAccessible(boolean)} throws a security exception. + */ + public <T> Constructor<T> transform(Constructor<T> x) { + if (x == null) + return null; + if (isVisible(x)) + if (! setAccessible(x)) + return null; + return x; + } + + /** + * Makes method accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't. + * Security exceptions thrown on the call to {@link Method#setAccessible(boolean)} are quietly ignored. + * + * @param x The method. + * @return The same method if visibility requirements met, or <jk>null</jk> if visibility requirement not + * met or call to {@link Method#setAccessible(boolean)} throws a security exception. + */ + public <T> Method transform(Method x) { + if (x == null) + return null; + if (isVisible(x)) + if (! setAccessible(x)) + return null; + return x; + } + + /** + * Makes field accessible if it matches the visibility requirements, or returns <jk>null</jk> if it doesn't. + * Security exceptions thrown on the call to {@link Field#setAccessible(boolean)} are quietly ignored. + * + * @param x The field. + * @return The same field if visibility requirements met, or <jk>null</jk> if visibility requirement not + * met or call to {@link Field#setAccessible(boolean)} throws a security exception. + */ + public Field transform(Field x) { + if (x == null) + return null; + if (isVisible(x)) + if (! setAccessible(x)) + return null; + return x; + } + + /** + * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. + * + * @param x The constructor. + * @return <jk>true</jk> if call was successful. + */ + public static boolean setAccessible(Constructor<?> x) { + try { + if (! (x == null || x.isAccessible())) + x.setAccessible(true); + return true; + } catch (SecurityException e) { + return false; + } + } + + /** + * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. + * + * @param x The method. + * @return <jk>true</jk> if call was successful. + */ + public static boolean setAccessible(Method x) { + try { + if (! (x == null || x.isAccessible())) + x.setAccessible(true); + return true; + } catch (SecurityException e) { + return false; + } + } + + /** + * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. + * + * @param x The field. + * @return <jk>true</jk> if call was successful. + */ + public static boolean setAccessible(Field x) { + try { + if (! (x == null || x.isAccessible())) + x.setAccessible(true); + return true; + } catch (SecurityException e) { + return false; + } + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/Writable.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/Writable.java b/org.apache.juneau/src/main/java/org/apache/juneau/Writable.java new file mode 100644 index 0000000..a14e544 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/Writable.java @@ -0,0 +1,42 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau; + +import java.io.*; + +/** + * Interface that identifies that an object can be serialized directly to a writer. + * <p> + * Instances must identify the media type of the content by implementing the + * {@link #getMediaType()} method. + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public interface Writable { + + /** + * Serialize this object to the specified writer. + * + * @param w The writer to write to. + * @throws IOException + */ + void writeTo(Writer w) throws IOException; + + /** + * Returns the serialized media type for this resource (e.g. <js>"text/html"</js>) + * + * @return The media type, or <jk>null</jk> if the media type is not known. + */ + String getMediaType(); +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Bean.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Bean.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Bean.java new file mode 100644 index 0000000..55b6468 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Bean.java @@ -0,0 +1,236 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.beans.*; +import java.lang.annotation.*; + +import org.apache.juneau.*; +import org.apache.juneau.transform.*; + +/** + * Used to tailor how beans get interpreted by the framework. + * <p> + * Can be used to do the following: + * <ul class='spaced-list'> + * <li>Explicitly specify the set and order of properties on a bean. + * <li>Associate a {@link PropertyNamer} with a class. + * <li>Specify subtypes of a bean differentiated by a sub type property. + * </ul> + * <p> + * This annotation can be applied to classes and interfaces. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(TYPE) +@Retention(RUNTIME) +@Inherited +public @interface Bean { + + /** + * The set and order of names of properties associated with a bean class. + * <p> + * The order specified is the same order that the entries will be returned by the {@link BeanMap#entrySet()} and related methods. + * <p> + * This annotation is an alternative to using the {@link BeanTransform} class with an implemented {@link BeanTransform#getProperties()} method. + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jc>// Address class with only street/city/state properties (in that order).</jc> + * <jc>// All other properties are ignored.</jc> + * <ja>@Bean</ja>(properties={<js>"street"</js>,<js>"city"</js>,<js>"state"</js>}) + * <jk>public class</jk> Address { + * ... + * </p> + * </dd> + * </dl> + */ + String[] properties() default {}; + + /** + * Sort bean properties in alphabetical order. + * <p> + * When <jk>true</jk>, all bean properties will be serialized and access in alphabetical order. + * Otherwise, the natural order of the bean properties is used which is dependent on the + * JVM vendor. + * On IBM JVMs, the bean properties are ordered based on their ordering in the Java file. + * On Oracle JVMs, the bean properties are not ordered (which follows the offical JVM specs). + * <p> + * This property is disabled by default so that IBM JVM users don't have to use {@link Bean @Bean} annotations + * to force bean properties to be in a particular order and can just alter the order of the fields/methods + * in the Java file. + * <p> + * This annotation is equivalent to using the {@link BeanContext#BEAN_sortProperties} property, but + * applied to individual classes instead of globally at the serializer or parser level. + */ + boolean sort() default false; + + /** + * Specifies a list of properties that should be excluded from {@link BeanMap#entrySet()}. + * <p> + * This annotation is an alternative to using the {@link BeanTransform} class with an implemented {@link BeanTransform#getExcludeProperties()} method. + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jc>// Address class with only street/city/state properties (in that order).</jc> + * <jc>// All other properties are ignored.</jc> + * <ja>@Bean</ja>(excludeProperties={<js>"city"</js>,<js>"state"</js>}) + * <jk>public class</jk> Address { + * ... + * </p> + * </dd> + * </dl> + */ + String[] excludeProperties() default {}; + + /** + * Associates a {@link PropertyNamer} with this bean to tailor the names of the bean properties. + * <p> + * Property namers are used to transform bean property names from standard form to some other form. + * For example, the {@link PropertyNamerDashedLC} will convert property names to dashed-lowercase, and + * these will be used as attribute names in JSON, and element names in XML. + * <p> + * This annotation is an alternative to using the {@link BeanTransform} class with an implemented {@link BeanTransform#getPropertyNamer()} method. + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jc>// Define a class with dashed-lowercase property names.</jc> + * <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>) + * <jk>public class</jk> MyClass { + * ... + * } + * </p> + * </dd> + * </dl> + */ + Class<? extends PropertyNamer> propertyNamer() default PropertyNamerDefault.class; + + /** + * Defines a virtual property on a superclass that identifies bean subtype classes. + * <p> + * In the following example, the abstract class has two subclasses that are differentiated + * by a property called <code>subType</code> + * <p class='bcode'> + * <jc>// Abstract superclass</jc> + * <ja>@Bean</ja>( + * subTypeProperty=<js>"subType"</js>, + * subTypes={ + * <ja>@BeanSubType</ja>(type=A1.<jk>class</jk>, id=<js>"A1"</js>), + * <ja>@BeanSubType</ja>(type=A2.<jk>class</jk>, id=<js>"A2"</js>) + * } + * ) + * <jk>public class</jk> A { + * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>; + * } + * + * <jc>// Subclass 1</jc> + * <jk>public class</jk> A1 <jk>extends</jk> A { + * <jk>public</jk> String <jf>f1</jf>; + * } + * + * <jc>// Subclass 2</jc> + * <jk>public class</jk> A2 <jk>extends</jk> A { + * <jk>public</jk> String <jf>f2</jf>; + * } + * <p> + * The following shows what happens when serializing a subclassed object to JSON: + * <p class='bcode'> + * JsonSerializer s = JsonSerializer.<jsf>DEFAULT_LAX</jsf>; + * A1 a1 = <jk>new</jk> A1(); + * a1.<jf>f1</jf> = <js>"f1"</js>; + * String r = s.serialize(a1); + * <jsm>assertEquals</jsm>(<js>"{subType:'A1',f1:'f1',f0:'f0'}"</js>, r); + * </p> + * <p> + * The following shows what happens when parsing back into the original object. + * <p> + * <p class='bcode'> + * JsonParser p = JsonParser.<jsf>DEFAULT</jsf>; + * A a = p.parse(r, A.<jk>class</jk>); + * <jsm>assertTrue</jsm>(a <jk>instanceof</jk> A1); + * </p> + * <p> + * This annotation is an alternative to using the {@link BeanTransform} class with an implemented {@link BeanTransform#getSubTypeProperty()} method. + */ + String subTypeProperty() default ""; + + /** + * Used in conjunction with {@link #subTypeProperty()} to set up bean subtypes. + */ + BeanSubType[] subTypes() default {}; + + /** + * Identifies a class to be used as the interface class for this and all subclasses. + * <p> + * When specified, only the list of properties defined on the interface class will be used during serialization. + * Additional properties on subclasses will be ignored. + * <p class='bcode'> + * <jc>// Parent class</jc> + * <ja>@Bean</ja>(interfaceClass=A.<jk>class</jk>) + * <jk>public abstract class</jk> A { + * <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>; + * } + * + * <jc>// Sub class</jc> + * <jk>public class</jk> A1 <jk>extends</jk> A { + * <jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>; + * } + * + * JsonSerializer s = JsonSerializer.<jsf>DEFAULT_LAX</jsf>; + * A1 a1 = <jk>new</jk> A1(); + * String r = s.serialize(a1); + * <jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, r); // Note f1 is not serialized. + * </p> + * <p> + * Note that this annotation can be used on the parent class so that it filters to all child classes, + * or can be set individually on the child classes. + * <p> + * This annotation is an alternative to using the {@link BeanTransform} class with an implemented {@link BeanTransform#getInterfaceClass()} method. + */ + Class<?> interfaceClass() default Object.class; + + /** + * Identifies a stop class for the annotated class. + * <p> + * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}. + * Any properties in the stop class or in its baseclasses will be ignored during analysis. + * <p> + * For example, in the following class hierarchy, instances of <code>C3</code> will include property <code>p3</code>, but + * not <code>p1</code> or <code>p2</code>. + * <p class='bcode'> + * <jk>public class</jk> C1 { + * <jk>public int</jk> getP1(); + * } + * + * <jk>public class</jk> C2 <jk>extends</jk> C1 { + * <jk>public int</jk> getP2(); + * } + * + * <ja>@Bean</ja>(stopClass=C2.<jk>class</jk>) + * <jk>public class</jk> C3 <jk>extends</jk> C2 { + * <jk>public int</jk> getP3(); + * } + * </p> + */ + Class<?> stopClass() default Object.class; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanConstructor.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanConstructor.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanConstructor.java new file mode 100644 index 0000000..875bbe4 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanConstructor.java @@ -0,0 +1,86 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.*; + +/** + * Maps constructor arguments to property names on beans with read-only properties. + * <p> + * This annotation can be used in the case of beans with properties whose values can only be set by passing + * them in through a constructor on the class.<br> + * Since method parameter names are lost during compilation, this annotation essentially redefines them + * so that they are available at runtime. + * <p> + * The definition of a read-only bean is a bean with properties with only getters, like shown below... + * <p class='bcode'> + * <jk>public class</jk> Person { + * <jk>private final</jk> String <jf>name</jf>; + * <jk>private final int</jk> <jf>age</jf>; + * + * <ja>@BeanConstructor</ja>(properties={<js>"name"</js>,<js>"age"</js>}) + * <jk>public</jk> Person(String name, <jk>int</jk> age) { + * <jk>this</jk>.<jf>name</jf> = name; + * <jk>this</jk>.<jf>age</jf> = age; + * } + * + * <jc>// Read only properties.</jc> + * + * <jk>public</jk> String getName() { + * <jk>return</jk> <jf>name</jf>; + * } + * + * <jk>public int</jk> getAge() { + * <jk>return</jk> <jf>age</jf>; + * } + * } + * + * String json = <js>"{name:'John Smith',age:45}"</js>; + * Person p = JsonParser.<jsf>DEFAULT</jsf>.parse(json); + * String name = p.getName(); <jc>// "John Smith"</jc> + * <jk>int</jk> age = p.getAge(); <jc>// 45</jc> + * </p> + * <p> + * This annotation can only be applied to constructors and can only be applied to one constructor per class. + * <p> + * When present, bean instantiation is delayed until the call to {@link BeanMap#getBean()}. + * Until then, bean property values are stored in a local cache until <code>getBean()</code> is called. + * Because of this additional caching step, parsing into read-only beans tends to be slower and use + * more memory than parsing into beans with writable properties. + * <p> + * Attempting to call {@link BeanMap#put(String,Object)} on a read-only property after calling {@link BeanMap#getBean()} + * will result in a {@link BeanRuntimeException} being thrown. + * Multiple calls to {@link BeanMap#getBean()} will return the same bean instance. + * <p> + * Beans can be defined with a combination of read-only and read-write properties. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(CONSTRUCTOR) +@Retention(RUNTIME) +@Inherited +public @interface BeanConstructor { + + /** + * The names of the properties of the constructor arguments. + * <p> + * The number of properties listed must match the number of arguments in the constructor. + */ + String[] properties() default {}; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanIgnore.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanIgnore.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanIgnore.java new file mode 100644 index 0000000..a976759 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanIgnore.java @@ -0,0 +1,38 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Ignore classes, fields, and methods from being interpreted as bean or bean components. + * <p> + * Applied to classes that may look like beans, but you want to be treated as non-beans. + * For example, if you want to force a bean to be converted to a string using the <code>toString()</code> + * method, use this annoation on the class. + * <p> + * Applies to fields that should not be interpreted as bean property fields. + * <p> + * Applies to getters or setters that should not be interpreted as bean property getters or setters. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target({FIELD,METHOD,TYPE}) +@Retention(RUNTIME) +@Inherited +public @interface BeanIgnore {} + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanProperty.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanProperty.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanProperty.java new file mode 100644 index 0000000..e9ff331 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanProperty.java @@ -0,0 +1,186 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.jena.*; +import org.apache.juneau.transform.*; +import org.apache.juneau.xml.*; +import org.apache.juneau.xml.annotation.*; + +/** + * Used tailor how bean properties get interpreted by the framework. + * <p> + * Can be used to do the following: + * <ul class='spaced-list'> + * <li>Override the name of a property. + * <li>Identify a getter or setter with a non-standard naming convention. + * <li>Identify a specific subclass for a property with a general class type. + * <li>Identify class types of elements in properties of type <code>Collection</code> or <code>Map</code>. + * <li>Hide properties during serialization. + * <li>Associate transforms with bean property values, such as a transform to convert a <code>Calendar</code> field to a string. + * <li>Override the list of properties during serialization on child elements of a property of type <code>Collection</code> or <code>Map</code>. + * <li>Identify a property as the URL for a bean. + * <li>Identify a property as the ID for a bean. + * </ul> + * <p> + * This annotation is applied to public fields and public getter/setter methods of beans. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target({FIELD,METHOD}) +@Retention(RUNTIME) +@Inherited +public @interface BeanProperty { + + /** + * Identifies the name of the property. + * <p> + * Normally, this is automatically inferred from the field name or getter method name + * of the property. However, this property can be used to assign a different + * property name from the automatically inferred value. + * <p> + * If the {@link BeanContext#BEAN_beanFieldVisibility} setting on the bean context excludes this field (e.g. the visibility + * is set to PUBLIC, but the field is PROTECTED), this annotation can be used to force the field to be identified as a property. + */ + String name() default ""; + + /** + * Identifies a specialized class type for the property. + * <p> + * Normally this can be inferred through reflection of the field type or getter return type. + * However, you'll want to specify this value if you're parsing beans where the bean property class + * is an interface or abstract class to identify the bean type to instantiate. Otherwise, you may + * cause an {@link InstantiationException} when trying to set these fields. + * <p> + * This property must denote a concrete bean class with a no-arg constructor. + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jk>public class</jk> MyBean { + * + * <jc>// Identify concrete map type.</jc> + * <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>) + * <jk>public</jk> Map <jf>p1</jf>; + * } + * </p> + * </dd> + * </dl> + */ + Class<?> type() default Object.class; + + /** + * For bean properties of maps and collections, this annotation can be used to identify + * the class types of the contents of the bean property object when the generic parameter + * types are interfaces or abstract classes. + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jk>public class</jk> MyBean { + * + * <jc>// Identify concrete map type with String keys and Integer values.</jc> + * <ja>@BeanProperty</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>}) + * <jk>public</jk> Map <jf>p1</jf>; + * } + * </p> + * </dd> + * </dl> + */ + Class<?>[] params() default {}; + + /** + * Associates an object transform with this bean property that will convert it + * to a different value during serialization and parsing. + * <p> + * This annotation supersedes any transform associated with the bean property type + * class itself. + * <p> + * Typically used for rendering {@link Date Dates} and {@link Calendar Calendars} + * as a particular string format. + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jk>public class</jk> MyClass { + * + * <jc>// During serialization, convert to ISO8601 date-time string.</jc> + * <ja>@BeanProperty</ja>(transform=CalendarTransform.ISO8601DT.<jk>class</jk>) + * <jk>public</jk> Calendar getTime(); + * } + * </p> + * </dd> + * </dl> + */ + Class<? extends PojoTransform<?,?>> transform() default PojoTransform.NULL.class; + + /** + * Used to limit which child properties are rendered by the serializers. + * <p> + * Can be used on any of the following bean property types: + * <ul class='spaced-list'> + * <li>Beans - Only render the specified properties of the bean. + * <li>Maps - Only render the specified entries in the map. + * <li>Bean/Map arrays - Same, but applied to each element in the array. + * <li>Bean/Map collections - Same, but applied to each element in the collection. + * </ul> + * + * <dl> + * <dt>Example:</dt> + * <dd> + * <p class='bcode'> + * <jk>public class</jk> MyClass { + * + * <jc>// Only render 'f1' when serializing this bean property.</jc> + * <ja>@BeanProperty</ja>(properties={<js>"f1"</js>}) + * <jk>public</jk> MyChildClass x1 = <jk>new</jk> MyChildClass(); + * } + * + * <jk>public class</jk> MyChildClass { + * <jk>public int</jk> f1 = 1; + * <jk>public int</jk> f2 = 2; + * } + * + * <jc>// Renders "{x1:{f1:1}}"</jc> + * String json = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jk>new</jk> MyClass()); + * </p> + * </dd> + * </dl> + */ + String[] properties() default {}; + + /** + * Marks a bean property as a resource URI identifier for the bean. + * <p> + * Has the following effects on the following serializers: + * <ul class='spaced-list'> + * <li>{@link XmlSerializer} - Will be rendered as an XML attribute on the bean element, unless + * marked with a {@link Xml#format} value of {@link XmlFormat#ELEMENT}. + * <li>{@link RdfSerializer} - Will be rendered as the value of the <js>"rdf:about"</js> attribute + * for the bean. + * </ul> + */ + boolean beanUri() default false; +} + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanSubType.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanSubType.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanSubType.java new file mode 100644 index 0000000..f4486a9 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/BeanSubType.java @@ -0,0 +1,46 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Maps a bean subclass with a string identifier. + * <p> + * Used in conjunction with {@link Bean#subTypes()} for defining mappings of bean subclasses with string identifiers. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target({}) +@Retention(RUNTIME) +@Inherited +public @interface BeanSubType { + + /** + * The bean subclass. + * <p> + * Must be a subclass or subinterface of the parent bean. + */ + Class<?> type(); + + /** + * A string identifier for this subtype. + * <p> + * This identifier is used in conjunction with the {@link Bean#subTypeProperty()} during serialization + * to create a <code>{subType:<js>'id'</js>}</code> property on the serialized object. + */ + String id(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Consumes.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Consumes.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Consumes.java new file mode 100644 index 0000000..f9db621 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Consumes.java @@ -0,0 +1,73 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.parser.*; + +/** + * Annotation used on subclasses of {@link Parser} to identify the media types that it consumes. + * + * + * <h6 class='topic'>Description</h6> + * <p> + * Provides a way to define the contents of {@link Parser#getMediaTypes()} through an annotation. + * <p> + * The {@link Parser#getMediaTypes()} default implementation gathers the media types by looking + * for this annotation. + * It should be noted that this annotation is optional and that the {@link Parser#getMediaTypes()} method can + * be overridden by subclasses to return the media types programmatically. + * + * + * <h6 class='topic'>Examples</h6> + * <p> + * Standard example: + * <p class='bcode'> + * <ja>@Consumes</ja>({<js>"application/json"</js>,<js>"text/json"</js>}) + * <jk>public class</jk> JsonParser <jk>extends</jk> ReaderParser {...} + * </p> + * <p> + * The media types can also be <code>media-range</code> values per + * <a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1'>RFC2616/14.1</a>. + * <p class='bcode'> + * <jc>// Consumes any text</jc> + * <ja>@Consumes</ja>({<js>"text\/*"</js>}) + * <jk>public class</jk> AnythingParser <jk>extends</jk> ReaderParser {...} + * + * <jc>// Consumes anything</jc> + * <ja>@Consumes</ja>({<js>"*\/*"</js>}) + * <jk>public class</jk> AnythingParser <jk>extends</jk> ReaderParser {...} + * </p> + * + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(TYPE) +@Retention(RUNTIME) +@Inherited +public @interface Consumes { + + /** + * The media types that the parser can handle. + * <p> + * Can contain meta-characters per the <code>media-type</code> specification of + * <a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1'>RFC2616/14.1</a> + * @return The media types that the parser can handle. + */ + String[] value() default {}; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/NameProperty.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/NameProperty.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/NameProperty.java new file mode 100644 index 0000000..dfc3926 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/NameProperty.java @@ -0,0 +1,35 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.ini.*; + +/** + * Identifies a setter as a method for setting the name of a POJO as it's known by + * its parent object. + * <p> + * For example, the {@link Section} class must know the name it's known by it's parent + * {@link ConfigFileImpl} class, so parsers will call this method with the sectio name + * using the {@link Section#setName(String)} method. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Target({METHOD}) +@Retention(RUNTIME) +@Inherited +public @interface NameProperty {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ParentProperty.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ParentProperty.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ParentProperty.java new file mode 100644 index 0000000..0b044bf --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ParentProperty.java @@ -0,0 +1,35 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.ini.*; + +/** + * Identifies a setter as a method for adding a parent reference to a child object. + * <p> + * Used by the parsers to add references to parent objects in child objects. + * For example, the {@link Section} class cannot exist outside the scope of a parent + * {@link ConfigFileImpl} class, so parsers will add a reference to the config file + * using the {@link Section#setParent(ConfigFileImpl)} method. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Target({METHOD}) +@Retention(RUNTIME) +@Inherited +public @interface ParentProperty {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Produces.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Produces.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Produces.java new file mode 100644 index 0000000..77f41f2 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Produces.java @@ -0,0 +1,86 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.serializer.*; + +/** + * Annotation used on subclasses of {@link Serializer} to identify the media types that it produces. + * + * + * <h6 class='topic'>Description</h6> + * <p> + * Provides a way to define the contents of {@link Serializer#getMediaTypes()} through an annotation. + * <p> + * The {@link Serializer#getMediaTypes()} default implementation gathers the media types by looking + * for this annotation. + * It should be noted that this annotation is optional and that the {@link Serializer#getMediaTypes()} method can + * be overridden by subclasses to return the media types programmatically. + * + * + * <h6 class='topic'>Examples</h6> + * <p> + * Standard example: + * <p class='bcode'> + * <ja>@Produces</ja>({<js>"application/json"</js>,<js>"text/json"</js>}) + * <jk>public class</jk> JsonSerializer <jk>extends</jk> WriterSerializer {...} + * </p> + * <p> + * The media types can also be <code>media-range</code> values per + * <a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1'>RFC2616/14.1</a>. + * When meta-characters are used, you should specify the {@link #contentType()} value to + * indicate the real media type value that can be set on the <code>Content-Type</code> response header. + * + * <p class='bcode'> + * <jc>// Produces any text</jc> + * <ja>@Produces</ja>(value=<js>"text\/*"</js>, contentType=<js>"text/plain"</js>) + * <jk>public class</jk> AnythingSerializer <jk>extends</jk> WriterSerializer {...} + * + * <jc>// Produces anything</jc> + * <ja>@Produces</ja>(value=<js>"*\/*"</js>, contentType=<js>"text/plain"</js>) + * <jk>public class</jk> AnythingSerializer <jk>extends</jk> WriterSerializer {...} + * </p> + * + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(TYPE) +@Retention(RUNTIME) +@Inherited +public @interface Produces { + + /** + * The media types that the serializer can handle. + * <p> + * Can contain meta-characters per the <code>media-type</code> specification of + * <a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1'>RFC2616/14.1</a> + * @return The media types that the parser can handle. + */ + String[] value() default {}; + + /** + * The content type that this serializer produces. + * <p> + * Can be used to override the <code>Content-Type</code> response type if the media types + * are <code>media-ranges</code> with meta-characters, or the <code>Content-Type</code> + * differs from the media type for some reason. + * @return The content type that this serializer produces, or blank if no overriding value exists. + */ + String contentType() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Remoteable.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Remoteable.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Remoteable.java new file mode 100644 index 0000000..5b68bb8 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Remoteable.java @@ -0,0 +1,27 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Identifies services whose Java class or methods can be invoked remotely. + */ +@Documented +@Target({TYPE,METHOD}) +@Retention(RUNTIME) +@Inherited +public @interface Remoteable {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ThreadSafe.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ThreadSafe.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ThreadSafe.java new file mode 100644 index 0000000..0fe4abb --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/ThreadSafe.java @@ -0,0 +1,29 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; + +import java.lang.annotation.*; + +/** + * Identifies a class as being thread-safe. + * <p> + * Used for documentation purposes only. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(TYPE) +@Inherited +public @interface ThreadSafe {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Transform.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Transform.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Transform.java new file mode 100644 index 0000000..f0029a6 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/Transform.java @@ -0,0 +1,86 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.serializer.*; +import org.apache.juneau.transform.*; + +/** + * Annotation that can be applied to a class to associate a transform with it. + * <p> + * Typically used to associate {@link PojoTransform PojoTransforms} with classes using annotations + * instead of programatically through a method such as {@link Serializer#addTransforms(Class...)}. + * + * <h6 class='topic'>Example</h6> + * <p> + * In this case, a transform is being applied to a bean that will force it to be serialized as a <code>String</code> + * <p class='bcode'> + * <jc>// Our bean class</jc> + * <ja>@Transform</ja>(BTransform.<jk>class</jk>) + * <jk>public class</jk> B { + * <jk>public</jk> String <jf>f1</jf>; + * } + * + * <jc>// Our transform to force the bean to be serialized as a String</jc> + * <jk>public class</jk> BTransform <jk>extends</jk> PojoTransform<B,String> { + * <jk>public</jk> String transform(B o) <jk>throws</jk> SerializeException { + * <jk>return</jk> o.f1; + * } + * <jk>public</jk> B normalize(String f, ClassMeta<?> hint) <jk>throws</jk> ParseException { + * B b1 = <jk>new</jk> B(); + * b1.<jf>f1</jf> = f; + * <jk>return</jk> b1; + * } + * } + * + * <jk>public void</jk> testTransform() <jk>throws</jk> Exception { + * WriterSerializer s = JsonSerializer.<jsf>DEFAULT</jsf>; + * B b = <jk>new</jk> B(); + * b.<jf>f1</jf> = <js>"bar"</js>; + * String json = s.serialize(b); + * <jsm>assertEquals</jsm>(<js>"'bar'"</js>, json); + * + * ReaderParser p = JsonParser.<jsf>DEFAULT</jsf>; + * b = p.parse(json, B.<jk>class</jk>); + * <jsm>assertEquals</jsm>(<js>"bar"</js>, t.<jf>f1</jf>); + * } + * </p> + * <p> + * Note that using this annotation is functionally equivalent to adding transforms to the serializers and parsers: + * <p class='bcode'> + * WriterSerializer s = <jk>new</jk> JsonSerializer.addTransforms(BTransform.<jk>class</jk>); + * ReaderParser p = <jk>new</jk> JsonParser.addTransforms(BTransform.<jk>class</jk>); + * </p> + * <p> + * It is technically possible to associate a {@link BeanTransform} with a bean class using this annotation. + * However in practice, it's almost always less code to simply use the {@link Bean @Bean} annotation. + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(TYPE) +@Retention(RUNTIME) +@Inherited +public @interface Transform { + + /** + * The transform class. + */ + Class<? extends org.apache.juneau.transform.Transform> value() default org.apache.juneau.transform.Transform.NULL.class; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/URI.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/URI.java b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/URI.java new file mode 100644 index 0000000..df1d02a --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/URI.java @@ -0,0 +1,68 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; +import java.net.*; + +import org.apache.juneau.serializer.*; + +/** + * Used to identify a class or bean property as a URI. + * <p> + * By default, instances of {@link URL} and {@link URI} are considered URIs during serialization, and are + * handled differently depending on the serializer (e.g. <code>HtmlSerializer</code> creates a hyperlink, + * <code>RdfXmlSerializer</code> creates an <code>rdf:resource</code> object, etc...). + * <p> + * This annotation allows you to identify other classes that return URIs via <code>toString()</code> as URI objects. + * <p> + * Relative URIs are automatically prepended with {@link SerializerContext#SERIALIZER_absolutePathUriBase} and {@link SerializerContext#SERIALIZER_relativeUriBase} + * during serialization just like relative <code>URIs</code>. + * <p> + * This annotation can be applied to classes, interfaces, or bean property methods for fields. + * + * <h6 class='topic'>Examples</h6> + * <p class='bcode'> + * + * <jc>// Applied to a class whose toString() method returns a URI.</jc> + * <ja>@URI</ja> + * <jk>public class</jk> MyURI { + * <ja>@Override</ja> + * <jk>public</jk> String toString() { + * <jk>return</jk> <js>"http://localhost:9080/foo/bar"</js>; + * } + * } + * + * <jc>// Applied to bean properties</jc> + * <jk>public class</jk> MyBean { + * + * <ja>@URI</ja> + * <jk>public</jk> String <jf>beanUri</jf>; + * + * <ja>@URI</ja> + * <jk>public</jk> String getParentUri() { + * ... + * } + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target({TYPE,FIELD,METHOD}) +@Retention(RUNTIME) +@Inherited +public @interface URI {} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/annotation/package.html ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/annotation/package.html b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/package.html new file mode 100644 index 0000000..5e0089b --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/annotation/package.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> + <script> + /* Replace all @code and @link tags. */ + window.onload = function() { + document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>'); + document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>'); + } + </script> +</head> +<body> +<p>General bean annotations</p> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/csv/CsvSerializer.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/csv/CsvSerializer.java b/org.apache.juneau/src/main/java/org/apache/juneau/csv/CsvSerializer.java new file mode 100644 index 0000000..19b73e5 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/csv/CsvSerializer.java @@ -0,0 +1,95 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.csv; + +import java.io.*; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.annotation.*; +import org.apache.juneau.serializer.*; + +/** + * TODO - Work in progress. CSV serializer. + */ +@Produces("text/csv") +@SuppressWarnings({"unchecked","rawtypes"}) +public final class CsvSerializer extends WriterSerializer { + + //-------------------------------------------------------------------------------- + // Overridden methods + //-------------------------------------------------------------------------------- + + @Override /* Serializer */ + protected void doSerialize(SerializerSession session, Object o) throws Exception { + Writer out = session.getWriter(); + BeanContext bc = session.getBeanContext(); + ClassMeta cm = bc.getClassMetaForObject(o); + Collection l = null; + if (cm.isArray()) { + l = Arrays.asList((Object[])o); + } else { + l = (Collection)o; + } + if (l.size() > 0) { + ClassMeta entryType = bc.getClassMetaForObject(l.iterator().next()); + if (entryType.isBean()) { + BeanMeta<?> bm = entryType.getBeanMeta(); + int i = 0; + for (BeanPropertyMeta pm : bm.getPropertyMetas()) { + if (i++ > 0) + out.append(','); + append(out, pm.getName()); + } + out.append('\n'); + for (Object o2 : l) { + i = 0; + BeanMap bean = bc.forBean(o2); + for (BeanPropertyMeta pm : bm.getPropertyMetas()) { + if (i++ > 0) + out.append(','); + append(out, pm.get(bean)); + } + out.append('\n'); + } + } + } + } + + private void append(Writer w, Object o) throws IOException { + if (o == null) + w.append("null"); + else { + String s = o.toString(); + boolean mustQuote = false; + for (int i = 0; i < s.length() && ! mustQuote; i++) { + char c = s.charAt(i); + if (Character.isWhitespace(c) || c == ',') + mustQuote = true; + } + if (mustQuote) + w.append('"').append(s).append('"'); + else + w.append(s); + } + } + + @Override /* Serializer */ + public CsvSerializer clone() { + try { + return (CsvSerializer)super.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); // Shouldn't happen. + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/csv/package.html ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/csv/package.html b/org.apache.juneau/src/main/java/org/apache/juneau/csv/package.html new file mode 100644 index 0000000..9dc8113 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/csv/package.html @@ -0,0 +1,62 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> + <script> + /* Replace all @code and @link tags. */ + window.onload = function() { + document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>'); + document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>'); + } + </script> +</head> +<body> +<p>CSV serialization and parsing support</p> + +<script> + function toggle(x) { + var div = x.nextSibling; + while (div != null && div.nodeType != 1) + div = div.nextSibling; + if (div != null) { + var d = div.style.display; + if (d == 'block' || d == '') { + div.style.display = 'none'; + x.className += " closed"; + } else { + div.style.display = 'block'; + x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' ); + } + } + } +</script> + +This code is currently work-in-progress. + +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/doc-files/AddressBook.html ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/doc-files/AddressBook.html b/org.apache.juneau/src/main/java/org/apache/juneau/doc-files/AddressBook.html new file mode 100644 index 0000000..10f6427 --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/doc-files/AddressBook.html @@ -0,0 +1,113 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css">@IMPORT url("../../../../../../javadoc.css");</style> +</head> +<body style='margin:0 20'> + <p></p> + <!-- ======================================================================================================== --> + <a id="AddressBookSampleSource"></a><h2 class='topic'>AddressBook sample source</h2> + <p> + Sample code use in various examples throughout the Javadocs. Represents a simple POJO model consisting + of a collection (<code>LinkedList</code>), beans (<code>Address</code>, <code>Person</code>), and a type 4a transformed type (<code>Calendar</code>). + </p> + <p> + Public fields are used for bean properties in-leu of getters and setters to reduce the size of the example. + Bean properties defined using getters and setters would work identically. + </p> + <a id="AddressBook"></a> + <h6 class='figure'>AddressBook.java</h6> + <p class='bcode'> + <jc>// A collection of people</jc> + <jk>public class</jk> AddressBook <jk>extends</jk> LinkedList<Person> { + + <jc>// Extra method for adding a person to this address book. + // Used in PojoIntrospector usage examples.</jc> + <jk>public void</jk> addPerson(String name, <jk>String</jk> birthDate, List<Address> addresses) { + add(<jk>new</jk> Person(name, birthdate, addresses)); + } + } + </p> + <a id="Address"></a> + <h6 class='figure'>Address.java</h6> + <p class='bcode'> + <jk>public class</jk> Address { + + <jc>// Bean properties</jc> + <jk>public</jk> String <jf>street</jf>, <jf>city</jf>, <jf>state</jf>; + <jk>public int</jk> <jf>zip</jf>; + <jk>public boolean</jk> <jf>isCurrent</jf>; + + <jc>// Bean constructor</jc> + <jk>public</jk> Address() {} + + <jc>// Other constructor</jc> + <jk>public</jk> Address(String street, String city, String state, <jk>int</jk> zip, <jk>boolean</jk> isCurrent) { + <jk>this</jk>.<jf>street</jf> = street; + <jk>this</jk>.<jf>city</jf> = city; + <jk>this</jk>.<jf>state</jf> = state; + <jk>this</jk>.<jf>zip</jf> = zip; + <jk>this</jk>.<jf>isCurrent</jf> = isCurrent; + } + } + </p> + <a id="Person"></a> + <h6 class='figure'>Person.java</h6> + <p class='bcode'> + <jk>public class</jk> Person { + + <jc>// Bean properties</jc> + <jk>public</jk> String <jf>name</jf>; + <jk>public int</jk> <jf>age</jf>; + <jk>public</jk> Calendar <jf>birthDate</jf>; + + <jk>public</jk> LinkedList<Address> <jf>addresses</jf> = <jk>new</jk> LinkedList<Address>(); + + <jc>// Bean constructor</jc> + <jk>public</jk> Person() {} + + <jc>// Other constructor</jc> + <jk>public</jk> Person(String name, String birthDate, Address...addresses) { + <jk>this</jk>.<jf>name</jf> = name; + <jk>this</jk>.<jf>birthDate</jf> = <jsm>getBirthDate</jsm>(birthDate); + <jk>this</jk>.<jf>age</jf> = <jsm>calcAge</jsm>(birthDate); + <jk>this</jk>.<jf>addresses</jf>.addAll(Arrays.<jsm>asList</jsm>(addresses)); + } + + <jc>// Other method</jc> + <jc>// Calculates a persons age based on the birthdate</jc> + <jk>public static int</jk> calcAge(String birthDate) { + <jk>return new</jk> GregorianCalendar().get(Calendar.<jsf>YEAR</jsf>) - getBirthDate(birthDate).get(Calendar.<jsf>YEAR</jsf>); + } + + <jc>// Utility method</jc> + <jc>// Converts a birthdate string to a Calendar</jc> + <jk>private static</jk> Calendar getBirthDate(String birthDate) { + <jk>try</jk> { + Calendar c = <jk>new</jk> GregorianCalendar(); + c.setTime(DateFormat.<jsm>getDateInstance</jsm>(DateFormat.<jsf>MEDIUM</jsf>).parse(birthDate)); + <jk>return</jk> c; + } <jk>catch</jk> (ParseException e) { + <jk>throw new</jk> RuntimeException(e); + } + } + } + </p> + +</body> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/dto/Link.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/dto/Link.java b/org.apache.juneau/src/main/java/org/apache/juneau/dto/Link.java new file mode 100644 index 0000000..080047d --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/dto/Link.java @@ -0,0 +1,137 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.dto; + +import java.text.*; + +import org.apache.juneau.html.*; +import org.apache.juneau.urlencoding.*; +import org.apache.juneau.utils.*; + +/** + * Simple bean that implements a hyperlink for the HTML serializer. + * <p> + * The name and url properties correspond to the following parts of a hyperlink in an HTML document... + * <p class='bcode'> + * <xt><a</xt> <xa>href</xa>=<xs>'href'</xs><xt>></xt>name<xt></a></xt> + * <p> + * When encountered by the {@link HtmlSerializer} class, this object gets converted to a hyperlink.<br> + * All other serializers simply convert it to a simple bean. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@HtmlLink(nameProperty = "name", hrefProperty = "href") +public class Link implements Comparable<Link> { + private String name, href; + + /** No-arg constructor. */ + public Link() {} + + /** + * Constructor. + * + * @param name Corresponds to the text inside of the <xt><A></xt> element. + * @param href Corresponds to the value of the <xa>href</xa> attribute of the <xt><A></xt> element. + * @param hrefArgs Optional arguments for {@link MessageFormat} style arguments in the href. + */ + public Link(String name, String href, Object...hrefArgs) { + setName(name); + setHref(href, hrefArgs); + } + + //-------------------------------------------------------------------------------- + // Bean properties + //-------------------------------------------------------------------------------- + + /** + * Bean property getter: <property>name</property>. + * Corresponds to the text inside of the <xt><A></xt> element. + * + * @return The value of the <property>name</property> property on this bean, or <jk>null</jk> if it is not set. + */ + public String getName() { + return name; + } + + /** + * Bean property setter: <property>name</property>. + * + * @param name The new value for the <property>name</property> property on this bean. + * @return This object (for method chaining). + */ + public Link setName(String name) { + this.name = name; + return this; + } + + /** + * Bean property getter: <property>href</property>. + * Corresponds to the value of the <xa>href</xa> attribute of the <xt><A></xt> element. + * + * @return The value of the <property>href</property> property on this bean, or <jk>null</jk> if it is not set. + */ + public String getHref() { + return href; + } + + /** + * Bean property setter: <property>href</property>. + * + * @param href The new value for the <property>href</property> property on this bean. + * @return This object (for method chaining). + */ + public Link setHref(String href) { + setHref(href, new Object[0]); + return this; + } + + /** + * Bean property setter: <property>href</property>. + * Same as {@link #setHref(String)} except allows for {@link MessageFormat} style arguments. + * + * @param href The new href. + * @param args Optional message format arguments. + * @return This object (for method chaining). + */ + public Link setHref(String href, Object...args) { + for (int i = 0; i < args.length; i++) + args[i] = UrlEncodingSerializer.DEFAULT.serializeUrlPart(args[i]); + this.href = (args.length > 0 ? MessageFormat.format(href, args) : href); + return this; + } + + /** + * Returns the name so that the {@link PojoQuery} class can search against it. + */ + @Override /* Object */ + public String toString() { + return name; + } + + @Override /* Comparable */ + public int compareTo(Link o) { + return name.compareTo(o.name); + } + + @Override /* Object */ + public boolean equals(Object o) { + if (! (o instanceof Link)) + return false; + return (compareTo((Link)o) == 0); + } + + @Override /* Object */ + public int hashCode() { + return super.hashCode(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau/src/main/java/org/apache/juneau/dto/ResultSetList.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau/src/main/java/org/apache/juneau/dto/ResultSetList.java b/org.apache.juneau/src/main/java/org/apache/juneau/dto/ResultSetList.java new file mode 100644 index 0000000..df4e1cc --- /dev/null +++ b/org.apache.juneau/src/main/java/org/apache/juneau/dto/ResultSetList.java @@ -0,0 +1,109 @@ +/*************************************************************************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + ***************************************************************************************************************************/ +package org.apache.juneau.dto; + +import java.sql.*; +import java.util.*; + +import org.apache.juneau.internal.*; + +/** + * Transforms an SQL {@link ResultSet ResultSet} into a list of maps. + * <p> + * Loads the entire result set into an in-memory data structure, and then closes the result set object. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public final class ResultSetList extends LinkedList<Map<String,Object>> { + + private static final long serialVersionUID = 1L; + + /** + * Constructor. + * + * @param rs The result set to load into this DTO. + * @param pos The start position (zero-indexed). + * @param limit The maximum number of rows to retrieve. + * @param includeRowNums Make the first column be the row number. + * @throws SQLException Database error. + */ + public ResultSetList(ResultSet rs, int pos, int limit, boolean includeRowNums) throws SQLException { + try { + int rowNum = pos; + + // Get the column names. + ResultSetMetaData rsmd = rs.getMetaData(); + int offset = (includeRowNums ? 1 : 0); + int cc = rsmd.getColumnCount(); + String[] columns = new String[cc + offset]; + if (includeRowNums) + columns[0] = "ROW"; + int[] colTypes = new int[cc]; + + for (int i = 0; i < cc; i++) { + columns[i+offset] = rsmd.getColumnName(i+1); + colTypes[i] = rsmd.getColumnType(i+1); + } + + while (--pos > 0 && rs.next()) {} + + // Get the rows. + while (limit-- > 0 && rs.next()) { + Object[] row = new Object[cc + offset]; + if (includeRowNums) + row[0] = rowNum++; + for (int i = 0; i < cc; i++) { + Object o = readEntry(rs, i+1, colTypes[i]); + row[i+offset] = o; + } + add(new SimpleMap(columns, row)); + } + } finally { + rs.close(); + } + } + + /** + * Reads the specified column from the current row in the result set. + * Subclasses can override this method to handle specific data types in special ways. + * + * @param rs The result set to read from. + * @param col The column number (indexed by 1). + * @param dataType The {@link Types type} of the entry. + * @return The entry as an Object. + */ + protected Object readEntry(ResultSet rs, int col, int dataType) { + try { + switch (dataType) { + case Types.BLOB: + Blob b = rs.getBlob(col); + return "blob["+b.length()+"]"; + case Types.CLOB: + Clob c = rs.getClob(col); + return "clob["+c.length()+"]"; + case Types.LONGVARBINARY: + return "longvarbinary["+IOUtils.count(rs.getBinaryStream(col))+"]"; + case Types.LONGVARCHAR: + return "longvarchar["+IOUtils.count(rs.getAsciiStream(col))+"]"; + case Types.LONGNVARCHAR: + return "longnvarchar["+IOUtils.count(rs.getCharacterStream(col))+"]"; + case Types.TIMESTAMP: + return rs.getTimestamp(col); // Oracle returns com.oracle.TIMESTAMP objects from getObject() which isn't a Timestamp. + default: + return rs.getObject(col); + } + } catch (Exception e) { + return e.getLocalizedMessage(); + } + } +}