View Javadoc

1   /*
2    * Copyright 2006 Outsource Cafe, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the 'License')
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an 'AS IS' BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.javagen.agile.core.model;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.Map;
22  
23  import javax.xml.bind.annotation.XmlAttribute;
24  import javax.xml.bind.annotation.XmlElement;
25  import javax.xml.bind.annotation.XmlElementRef;
26  import javax.xml.bind.annotation.XmlID;
27  import javax.xml.bind.annotation.XmlTransient;
28  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
29  
30  import org.javagen.agile.core.context.ContextHolder;
31  import org.javagen.agile.core.context.DefaultContext;
32  import org.javagen.agile.core.util.ModelUtil;
33  import org.javagen.agile.core.util.StringUtil;
34  import org.javagen.agile.core.xml.jaxb.ContextTypeAdapter;
35  
36  /***
37   * Generic implementation of Model interface.  See <code>Model</code> for documentation.
38   * Xml binding annotations are defined to support serialization of subclasses of AbstractModel.
39   * 
40   * @author Richard Easterling
41   */
42  public abstract class AbstractModel implements  Model, ContextHolder, Serializable {
43  
44  	protected String name;
45  	protected String id;
46  	protected String modelType;
47  	protected Map<String, Object> context;
48  	protected Model parentModel;
49  	protected List<Model> childModels;
50      
51      public AbstractModel() { }
52      
53      public AbstractModel(String name) {
54          setName(name);
55      }
56  	
57      @XmlAttribute
58  	public String getName() {
59  		return name;
60  	}
61  
62  	public void setName(String name) {
63  		this.name = name;
64  	}
65  
66      @XmlAttribute @XmlID
67  	public String getId() {
68  		return id;
69  	}
70  
71  	public void setId(String id) {
72  		this.id = id;
73  	}
74  	
75      @XmlAttribute
76      public String getModelType() {
77          return modelType;
78      }
79  
80      public void setModelType(String modelType) {
81          this.modelType = modelType;
82      }
83          
84      ////////////////////////////////////////////////////////////////////////////
85      // misc methods:
86      ////////////////////////////////////////////////////////////////////////////
87      
88      @Override
89      public String toString() {
90          StringBuilder sb = new StringBuilder();
91          sb.append(StringUtil.lastToken(this.getClass().getName(), '.'));
92          sb.append("[name=").append(getName());
93          if (getId()!=null)
94              sb.append(", id=").append(getId());
95          if (this.getModelType()!=null)
96              sb.append(", modelType=").append(getModelType());
97          sb.append("]");
98          return sb.toString();
99      }
100 
101     @Override
102     public boolean equals(Object obj) {
103         if ( ! (obj instanceof Model) )
104             return false;
105         Model other = (Model)obj;
106         if ((name!=null && !name.equals(other.getName())) || other.getName()!=null)
107             return false;
108         if ((id!=null && !id.equals(other.getId())) || other.getId()!=null)
109             return false;
110         if ((modelType!=null && !modelType.equals(other.getModelType())) || other.getModelType()!=null)
111             return false;
112 //        if ( (childModels==null ? 0 : childModels.size()) != (other.getChildModels()==null ? 0 : other.getChildModels().size()))
113 //            return false;
114         return true;
115     }
116 
117 	////////////////////////////////////////////////////////////////////////////
118 	// Model tree creation and navigation:
119 	////////////////////////////////////////////////////////////////////////////
120 	
121     //@XmlIDREF
122     //@XmlElement(type=AbstractModel.class)
123     @XmlTransient
124 	public Model getParentModel() {
125 		return parentModel;
126 	}
127 	
128 	public void setParentModel(Model parentModel) { 
129 		this.parentModel = parentModel;
130 	}
131 	
132     /***
133      * @return the assigned List or if null an immutable empty list constant.
134      */
135     @XmlElementRef(type=AbstractModel.class)
136     public List<Model> getChildModels() {
137         if (childModels==null)
138             childModels = new ArrayList<Model>();
139 		return childModels;
140 	}
141 	
142     /***
143      * Set child models, making sure the parent is set.
144      */
145 	public void setChildModels(List<Model> childModels) {
146         this.childModels = childModels;
147         if (childModels!=null) {
148             for(Model child : this.childModels)
149                 child.setParentModel(this);
150         }
151 	}
152 
153     /***
154      * Add child model, making sure the parent is set.
155      */
156 	public void addChildModel(Model child) {
157 		if (childModels == null)
158 			childModels = new ArrayList<Model>();
159 		childModels.add(child);
160 		child.setParentModel(this);
161 	}
162 	
163 	public Model lookupChildByName(String name) {
164 		return ModelUtil.lookupChildByName(this, name, false);
165 	}
166 
167     public List<Model> allOwnedModels() {
168         return getChildModels();
169     }
170     
171 	////////////////////////////////////////////////////////////////////////////
172 	// Model context:
173 	////////////////////////////////////////////////////////////////////////////
174 	
175     public Object get(String key) {
176         return context == null ? null : context.get(key);
177     }
178 
179     public void put(String key, Object value) {
180         if (context == null) {
181             context = new DefaultContext();
182         }
183         context.put(key, value);
184 
185     }
186 
187     @XmlElement 
188     @XmlJavaTypeAdapter(ContextTypeAdapter.class)
189 	public Map<String,Object> getContext() {
190 		return context;
191 	}
192 
193 	public void setContext(Map<String,Object> context) {
194 		this.context = context;
195 	}
196 
197 	////////////////////////////////////////////////////////////////////////////
198 	// template customization method:
199 	////////////////////////////////////////////////////////////////////////////
200 	
201 	public void copyTo(Model target) {
202 		if (target==null)
203 			throw new IllegalArgumentException("target can not be null");
204         if (this.getName()!=null && (target.getName()==null || !this.getName().equals(target.getName())))
205             target.setName(this.getName());
206         if (this.getId()!=null && target.getId()==null) //id should normally be set explicitly
207             target.setId(this.getId());
208         if (this.getModelType()!=null && target.getModelType()==null) //has a default value which we usually don't want
209             target.setModelType(this.getModelType());
210         if (this.getContext()!=null) {
211             for(String key : this.getContext().keySet()) {
212                 Object value = this.getContext().get(key);
213                 target.put(key, value);
214             }
215         }
216 	}
217     
218 }