001    /*
002     * Copyright 2004 Chris Nelson
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
007     * Unless required by applicable law or agreed to in writing,
008     * software distributed under the License is distributed on an "AS IS" BASIS,
009     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
010     * See the License for the specific language governing permissions and limitations under the License.
011     */
012    package org.tynamo.descriptor;
013    
014    import ognl.Ognl;
015    import ognl.OgnlException;
016    import org.apache.commons.beanutils.BeanUtils;
017    
018    import java.lang.reflect.InvocationTargetException;
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    
023    /**
024     * This represents all the Tynamo metadata for a single class.
025     */
026    public class TynamoClassDescriptorImpl extends TynamoDescriptor implements TynamoClassDescriptor
027    {
028            private List<TynamoPropertyDescriptor> propertyDescriptors = new ArrayList<TynamoPropertyDescriptor>();
029    
030            private List<IMethodDescriptor> methodDescriptors = new ArrayList<IMethodDescriptor>();
031    
032            // private BeanDescriptor beanDescriptor;
033            private boolean child;
034    
035            boolean hasCyclicRelationships;
036    
037            boolean allowRemove = true;
038    
039            boolean allowSave = true;
040    
041            // ///////////////////////////////////////////////////////////////////////////////////////////////////////
042            // Constructors
043            // ///////////////////////////////////////////////////////////////////////////////////////////////////////
044            /**
045             * This is a copy constructor. These need to be clonable for the security
046             * aspect to be able to copy them, so if new properties are added they
047             * should be added here too.
048             */
049            public TynamoClassDescriptorImpl(TynamoClassDescriptor descriptor)
050            {
051                    super(descriptor);
052                    copyPropertyDescriptorsFrom(descriptor);
053                    copyMethodDescriptorsFrom(descriptor);
054            }
055    
056            public TynamoClassDescriptorImpl(Class type)
057            {
058                    super(type);
059            }
060    
061            /**
062             * @param dto
063             */
064            public TynamoClassDescriptorImpl(TynamoClassDescriptorImpl dto)
065            {
066                    super(dto);
067    
068                    try
069                    {
070                            BeanUtils.copyProperties(this, dto);
071                    } catch (IllegalAccessException e)
072                    {
073                            LOG.error(e.getMessage());
074                            e.printStackTrace();
075                    } catch (InvocationTargetException e)
076                    {
077                            LOG.error(e.getMessage());
078                            e.printStackTrace();
079                    } catch (Exception e)
080                    {
081                            LOG.error(e.toString());
082                            e.printStackTrace();
083                    }
084            }
085    
086            // ///////////////////////////////////////////////////////////////////////////////////////////////////////
087            // Methods
088            // ///////////////////////////////////////////////////////////////////////////////////////////////////////
089            private void copyMethodDescriptorsFrom(TynamoClassDescriptor descriptor)
090            {
091                    for (IMethodDescriptor methodDescriptor : descriptor
092                            .getMethodDescriptors())
093                    {
094                            getMethodDescriptors().add(
095                                    IMethodDescriptor.class.cast(methodDescriptor.clone()));
096                    }
097            }
098    
099            protected void copyPropertyDescriptorsFrom(TynamoClassDescriptor descriptor)
100            {
101                    for (TynamoPropertyDescriptor iPropertyDescriptor : descriptor
102                            .getPropertyDescriptors())
103                    {
104                            getPropertyDescriptors()
105                                    .add(
106                                            TynamoPropertyDescriptor.class.cast(iPropertyDescriptor
107                                                    .clone()));
108                    }
109            }
110    
111            /**
112             * @param ognl
113             * @return
114             */
115            private TynamoPropertyDescriptor findDescriptor(String ognl)
116            {
117                    try
118                    {
119                            return (TynamoPropertyDescriptor) Ognl.getValue(ognl, this);
120                    } catch (OgnlException oe)
121                    {
122                            // oe.printStackTrace();
123    
124                            return null;
125                    } catch (IndexOutOfBoundsException ie)
126                    {
127                            return null;
128                    }
129            }
130    
131            /**
132             * @param string
133             * @return
134             */
135            public TynamoPropertyDescriptor getPropertyDescriptor(String name)
136            {
137                    return findDescriptor("propertyDescriptors.{? name == '" + name + "'}[0]");
138            }
139    
140            public List<TynamoPropertyDescriptor> getPropertyDescriptors(List<String> properties) {
141                    ArrayList<TynamoPropertyDescriptor> descriptors = new ArrayList<TynamoPropertyDescriptor>();
142                    for (String property : properties) {
143                            descriptors.add(getPropertyDescriptor(property));
144                    }
145                    return descriptors;
146            }
147    
148            // ///////////////////////////////////////////////////////////////////////////////////////////////////////
149            // bean getters / setters
150            // ///////////////////////////////////////////////////////////////////////////////////////////////////////
151            /**
152             * @return Returns the methodDescriptors.
153             */
154            public List<IMethodDescriptor> getMethodDescriptors()
155            {
156                    return methodDescriptors;
157            }
158    
159            /**
160             * @param methodDescriptors The methodDescriptors to set.
161             */
162            public void setMethodDescriptors(List<IMethodDescriptor> methodDescriptors)
163            {
164                    this.methodDescriptors = methodDescriptors;
165            }
166    
167            /**
168             * @return Returns the propertyDescriptors.
169             */
170            public List<TynamoPropertyDescriptor> getPropertyDescriptors()
171            {
172                    return propertyDescriptors;
173            }
174    
175            /**
176             * @param propertyDescriptors The propertyDescriptors to set.
177             */
178            public void setPropertyDescriptors(
179                    List<TynamoPropertyDescriptor> propertyDescriptors)
180            {
181                    this.propertyDescriptors = propertyDescriptors;
182            }
183    
184            public TynamoPropertyDescriptor getIdentifierDescriptor()
185            {
186                    String ognl = "propertyDescriptors.{? identifier}[0]";
187    
188                    return findDescriptor(ognl);
189            }
190    
191            /**
192             * @return Returns the child.
193             */
194            public boolean isChild()
195            {
196                    return child;
197            }
198    
199            /**
200             * @param child The child to set.
201             */
202            public void setChild(boolean child)
203            {
204                    this.child = child;
205            }
206    
207            @Override
208            public Object clone()
209            {
210                    return new TynamoClassDescriptorImpl(this);
211            }
212    
213            @Override
214            public void copyFrom(Descriptor descriptor)
215            {
216                    super.copyFrom(descriptor);
217    
218                    if (descriptor instanceof TynamoClassDescriptorImpl)
219                    {
220    
221                            try
222                            {
223                                    BeanUtils.copyProperties(this,
224                                            (TynamoClassDescriptorImpl) descriptor);
225                                    copyPropertyDescriptorsFrom((TynamoClassDescriptorImpl) descriptor);
226                                    copyMethodDescriptorsFrom((TynamoClassDescriptorImpl) descriptor);
227                            } catch (IllegalAccessException e)
228                            {
229                                    LOG.error(e.getMessage());
230                                    e.printStackTrace();
231                            } catch (InvocationTargetException e)
232                            {
233                                    LOG.error(e.getMessage());
234                                    e.printStackTrace();
235                            } catch (Exception e)
236                            {
237                                    LOG.error(e.toString());
238                                    e.printStackTrace();
239                            }
240                    }
241            }
242    
243            public boolean isAllowRemove()
244            {
245                    return allowRemove;
246            }
247    
248            public void setAllowRemove(boolean allowRemove)
249            {
250                    this.allowRemove = allowRemove;
251            }
252    
253            public boolean isAllowSave()
254            {
255                    return allowSave;
256            }
257    
258            public void setAllowSave(boolean allowSave)
259            {
260                    this.allowSave = allowSave;
261            }
262    
263            public boolean getHasCyclicRelationships()
264            {
265                    return hasCyclicRelationships;
266            }
267    
268            public void setHasCyclicRelationships(boolean hasBidirectionalRelationship)
269            {
270                    this.hasCyclicRelationships = hasBidirectionalRelationship;
271            }
272    
273            /**
274             * Added toString method to help with unit testing debugging.
275             */
276            public String toString()
277            {
278                    return "{TynamoClassDescriptor - Type: " + getType() + "}";
279            }
280    
281    }