View Javadoc

1   package org.andromda.core.translation.library;
2   
3   import java.util.ArrayList;
4   import java.util.Collection;
5   import java.util.Iterator;
6   import java.util.LinkedHashMap;
7   import java.util.Map;
8   
9   import org.andromda.core.common.ExceptionUtils;
10  import org.andromda.core.translation.TranslationUtils;
11  import org.apache.commons.lang.StringUtils;
12  import org.apache.commons.lang.builder.ToStringBuilder;
13  
14  
15  /***
16   * Represents a translation XML template found within a translation library.
17   *
18   * @author Chad Brandon
19   */
20  public class Translation
21  {
22      private String name;
23      private final Map fragments = new LinkedHashMap();
24      private final Collection ignorePatterns = new ArrayList();
25      private Collection validatePatterns;    // (wouter) TODO: Chad, this field is only updated, never queried, can we remove it ? 
26  
27      /***
28       * The library translation to which this translation belongs.
29       */
30      private LibraryTranslation libraryTranslation;
31  
32      /***
33       * Gets the LibraryTranslation to which this Translation belongs.
34       *
35       * @return LibraryTranslation
36       */
37      protected LibraryTranslation getLibraryTranslation()
38      {
39          final String methodName = "Translation.getLibraryTranslation";
40  
41          // should never happen, but it doesn't hurt to be safe
42          if (this.libraryTranslation == null)
43          {
44              throw new LibraryException(methodName + " - libraryTranslation can not be null");
45          }
46          return libraryTranslation;
47      }
48  
49      /***
50       * Sets the LibraryTranslation to which this Translation belongs.
51       *
52       * @param translation the LibraryTranslation to which this Translation belongs.
53       */
54      protected void setLibraryTranslation(final LibraryTranslation translation)
55      {
56          libraryTranslation = translation;
57      }
58  
59      /***
60       * Gets the fragment matching (using regular expressions) the specified name.
61       *
62       * @param name the name of the fragment to retrieve.
63       * @return Fragment
64       */
65      protected Fragment getFragment(final String name)
66      {
67          Fragment fragment = null;
68          Iterator names = fragments.keySet().iterator();
69  
70          // search through the names and the first name that matches
71          // one of the names return the value of that name.
72          while (names.hasNext())
73          {
74              String nextName = (String)names.next();
75              if (name.matches(nextName))
76              {
77                  fragment = (Fragment)fragments.get(nextName);
78              }
79          }
80  
81          // if the fragment is null, and the name isn't in an ignorePattern
82          // element, then give an error
83          if (fragment == null && !this.isIgnorePattern(name))
84          {
85              // TODO: make this work correctly with unsupported functions.
86  
87              /*
88               * logger.error("ERROR! expression fragment '" + name + "' is not
89               * currently supported --> add a <fragment/> with " + " a name that
90               * matches this expression to your translation file " + "'" +
91               * this.getLibraryTranslation().getFile() + "' to enable support");
92               */
93          }
94          return fragment;
95      }
96  
97      /***
98       * Adds a new Translation fragment to the Translation.
99       *
100      * @param fragment
101      */
102     public void addFragment(final Fragment fragment)
103     {
104         ExceptionUtils.checkNull(
105             "fragment",
106             fragment);
107         fragment.setTranslation(this);
108         this.fragments.put(
109             fragment.getName(),
110             fragment);
111     }
112 
113     /***
114      * Gets the name of this Translation.
115      *
116      * @return String
117      */
118     protected String getName()
119     {
120         return name;
121     }
122 
123     /***
124      * @param name
125      */
126     protected void setName(final String name)
127     {
128         this.name = name;
129     }
130 
131     /***
132      * Adds an <code>ignorePattern</code> to the Collection of ignorePatterns.
133      *
134      * @param ignorePattern the pattern to ignore.
135      */
136     public void addIgnorePattern(final String ignorePattern)
137     {
138         this.ignorePatterns.add(StringUtils.trimToEmpty(ignorePattern));
139     }
140 
141     /***
142      * Adds an <code>validatePattern</code> to the Collection of validatePatterns.
143      *
144      * @param validatePattern the pattern to validate.
145      */
146     public void addValidatePattern(final String validatePattern)
147     {
148         this.validatePatterns.add(StringUtils.trimToEmpty(validatePattern));
149     }
150 
151     /***
152      * Checks to see if the pattern is an ignore pattern. What this means is that if if this pattern matches on a
153      * regular expression found in the collection of ignore patterns then the TranslationLibrary won't complain if it
154      * doesn't match a fragment name.
155      *
156      * @param pattern
157      * @return boolean <code>true</code> if its an ignore pattern, <code>false</code> otherwise.
158      */
159     public boolean isIgnorePattern(String pattern)
160     {
161         boolean isIgnorePattern = false;
162         pattern = StringUtils.trimToEmpty(pattern);
163         Iterator ignorePatterns = this.ignorePatterns.iterator();
164 
165         // search through the ignorePatterns and see if one
166         // of them matches the passed in pattern.
167         while (ignorePatterns.hasNext())
168         {
169             String nextIgnorePattern = StringUtils.trimToEmpty((String)ignorePatterns.next());
170             isIgnorePattern = pattern.matches(nextIgnorePattern);
171             if (isIgnorePattern)
172             {
173                 break;
174             }
175         }
176         return isIgnorePattern;
177     }
178 
179     /***
180      * Gets the "translated" value of this Fragment if it exists. That is, it retrieves the fragment body for the name
181      * of this fragment and replaces any fragment references with other fragment bodies (if they exist)
182      *
183      * @param name the name of the fragment.
184      * @param kind the kind of the fragment.
185      * @return String the translated body of the fragment kind.
186      */
187     protected String getTranslated(
188         String name,
189         String kind)
190     {
191         // clean the strings first
192         name = StringUtils.trimToEmpty(name);
193         kind = StringUtils.trimToEmpty(kind);
194 
195         ExceptionUtils.checkEmpty(
196             "name",
197             name);
198 
199         Fragment fragment = this.getFragment(name);
200         String translated = "";
201         if (fragment != null)
202         {
203             translated = fragment.getKind(kind);
204             String begin = "fragment{";
205             int beginLength = begin.length();
206             String end = "}";
207             for (int beginIndex = translated.indexOf(begin); beginIndex != -1;
208                 beginIndex = translated.indexOf(begin))
209             {
210                 String fragmentName = translated.substring(
211                         beginIndex + beginLength,
212                         translated.length());
213                 int endIndex = fragmentName.indexOf(end);
214                 if (endIndex != -1)
215                 {
216                     fragmentName = fragmentName.substring(
217                             0,
218                             endIndex);
219                 }
220                 StringBuffer toReplace = new StringBuffer(begin);
221                 toReplace.append(fragmentName);
222                 toReplace.append(end);
223                 translated =
224                     StringUtils.replace(
225                         translated,
226                         toReplace.toString(),
227                         this.getTranslated(
228                             fragmentName,
229                             kind));
230             }
231         }
232         return TranslationUtils.removeExtraWhitespace(translated);
233     }
234 
235     /***
236      * @see java.lang.Object#toString()
237      */
238     public String toString()
239     {
240         return ToStringBuilder.reflectionToString(this);
241     }
242 }