[jboss-user] [JBoss Seam] - Re: ResourceBundle in Database

Zerg-Spirit do-not-reply at jboss.com
Tue Sep 11 03:15:34 EDT 2007


@Scope(APPLICATION)
  | @BypassInterceptors
  | @Name("org.jboss.seam.core.resourceLoader")
  | public class ExtendedResourceLoader extends
  | org.jboss.seam.core.ResourceLoader {
  | 
  | 	/**
  | 	 * Method called to load a bundle
  | 	 * @param bundleName the name of the bundle to load.
  | 	 * @return the ResourceBundle.
  | 	 */
  | 	public ResourceBundle loadBundle(final String bundleName) {
  | 		return new CustomResourceBundle();
  | 	}
  | 
  | 	/**
  | 	 * Private ResourceBundle fetching messages from the database
  | 	 */
  | 	private class CustomResourceBundle extends ResourceBundle{
  | 		java.util.Locale locale;
  |                 //the Locale of that ResourceBundle
  | 		Map<String,String> map;
  |                 //this map store the messages in the database
  | 
  | 		public CustomResourceBundle(){
  | 			locale = Locale.instance();
  | 		}
  | 
  | 		@Override
  | 		public Enumeration<String> getKeys() {
  | 			if(map == null){
  | 				map = new HashMap<String,String>();
  | 			}		
  | 			map = fetchExpressionsForLocale(locale.toString());
  | 			Vector v = new Vector(map.keySet());
  | 			return v.elements();
  | 		}
  | 
  | 		@Override
  | 		protected Object handleGetObject(String key) {
  | 			java.util.Locale locale = org.jboss.seam.core.Locale.instance();
  | 			if(map==null)
  | 				getKeys();
  | 			if(DBControl.instance().isDirtyLocale(locale.toString()) || DBControl.instance().isDirtyLocale("ALL")){
  | 				/*checking if this ResourceBundle is dirty, if so, re-fetching updated datas from the database. It might not be a nice way to check it, but I didn't find an other way.*/
  | 				getKeys();
  | 			        DBControl.instance().removeDirtyLocale(locale.toString());
  | 			}
  | 			if(map.containsKey(key))
  | 				return map.get(key);
  | 			else
  | 				return key;
  |                                 //returning the key if no proper message were found
  | 		}
  | 	}
  | 	
  | 	/**
  | 	 * Fetching the expressions from the database matching the current          Locale
  | 	 * @param locale
  | 	 * @return a map containing the translation
  | 	 */
  | 	private Map<String,String> fetchExpressionsForLocale(String locale){
  | 		EntityManager entityManager = (EntityManager) Component.getInstance("entityManager");
  | 		Map<String,String> map = new HashMap<String,String>();
  | 		boolean found = false;
  | 		List<Message> messages = entityManager.createQuery("select message from Message message").getResultList();
  | 		for(Message m: messages){
  | 			entityManager.refresh(m);
  |                         /*I'm obliged to do so, cause if 2 Locales are loaded in a short time, and a change was performed in the database, the entityManager seems to use its cache and not the proper data from the db.*/
  | 			for(Expression e: m.getExpressions()){
  | 			//seeking the proper Expression for the current Locale
  | 				if(e.getLanguage().getCode().equals(locale.toString())){
  | 					map.put(m.getKeyValue(), e.getText());
  | 					found = true;
  | 				}
  | 			}
  | 			if(!found){
  | 				//If no proper Expression found for the current locale, adding the expression for the default Locale
  | 				for(Expression e: m.getExpressions()){
  | 					if(e.getLanguage().isDefaultLanguage()){
  | 						map.put(m.getKeyValue(), e.getText());
  | 						found = true;
  | 					}
  | 				}
  | 				if(!found){
  | 					//else, we put the key as its own translation
  | 					map.put(m.getKeyValue(), m.getKeyValue());
  | 				}
  | 			}
  | 			found = false;
  | 		}
  | 		return map;
  | 	}
  | }
Note: in my code, a 'Message' is an Entity containing the message keys, and an expression is its translation for a given Locale (Expression table has a link to Language table, Language.code being for example 'en'). Note that I also have a 'default' language to fetch an expression if none was found for a given Locale.
Now my little class DBControl, just a singleton to handle 'dirty locales':

  | /**
  |  * Little singleton class handling dirty Locales
  |  */
  | public class DBControl{
  | 
  | 	private static DBControl instance;
  | 	private List<String> dirtyLocales;
  | 
  | 	private DBControl(){}
  | 
  | 	public static DBControl instance(){
  | 		if(instance==null)
  | 			instance = new DBControl();
  | 		return instance;
  | 	}
  | 
  | 	public void setDirtyLocale(String locale){
  | 		if(dirtyLocales==null)
  | 			dirtyLocales = new ArrayList<String>();
  | 		if(!dirtyLocales.contains(locale))
  | 			dirtyLocales.add(locale);
  | 	}
  | 
  | 	public void removeDirtyLocale(String locale){
  | 		if(dirtyLocales!=null){
  | 			for(String s: dirtyLocales){
  | 				if(s.equals(locale)){
  | 					dirtyLocales.remove(s);
  | 					break;
  | 				}
  | 			}
  | 		}
  | 	}
  | 	public boolean isDirtyLocale(String locale){
  | 		if(dirtyLocales!=null){
  | 			for(String s: dirtyLocales){
  | 				if(s.equals(locale))
  | 					return true;
  | 			}
  | 			return false;
  | 		}
  | 		else
  | 			return false;
  | 	}
  | }

Thanks to that class, I can access the 'dirtyLocales' list in both my Beans and my ResourceLoader.

Again, don't know if that's really a proper way to do it, waiting for feedback.

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4082856#4082856

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4082856



More information about the jboss-user mailing list