001    package org.trails.io;
002    
003    import org.apache.commons.logging.Log;
004    import org.apache.commons.logging.LogFactory;
005    import org.apache.hivemind.ApplicationRuntimeException;
006    import org.apache.tapestry.services.DataSqueezer;
007    import org.apache.tapestry.util.io.SqueezeAdaptor;
008    import org.trails.util.Utils;
009    import org.trails.descriptor.DescriptorService;
010    import org.trails.descriptor.IClassDescriptor;
011    import org.trails.engine.encoders.abbreviator.EntityNameAbbreviator;
012    import org.trails.persistence.PersistenceService;
013    import org.trails.builder.BuilderDirector;
014    import org.trails.exception.TrailsRuntimeException;
015    
016    import java.io.Serializable;
017    
018    /**
019     * This class is a Trails adaptation of Tapernate's EntitySqueezerFilter Squeezes persistent entities
020     */
021    public class EntitySqueezerStrategy implements SqueezeFilter, SqueezeAdaptor
022    {
023            private static final Log LOG = LogFactory.getLog(EntitySqueezerStrategy.class);
024    
025            String delimiter;
026            String prefix;
027    
028            private DescriptorService descriptorService;
029    
030            private PersistenceService persistenceService;
031    
032            private EntityNameAbbreviator entityNameAbbreviator;
033            private boolean shouldAbbreviate = false;
034    
035            private BuilderDirector builderDirector;
036    
037            public String getPrefix()
038            {
039                    return prefix;
040            }
041    
042            public Class getDataClass()
043            {
044                    return Squeezable.class;
045            }
046    
047            public String squeeze(DataSqueezer dataSqueezer, Object o)
048            {
049                    return squeeze(o, dataSqueezer);
050            }
051    
052            public Object unsqueeze(DataSqueezer dataSqueezer, String s)
053            {
054                    return unsqueeze(s, dataSqueezer);
055            }
056    
057            public String squeeze(Object data, DataSqueezer next)
058            {
059    
060                    if (data != null)
061                    {
062                            IClassDescriptor classDescriptor = descriptorService.getClassDescriptor(data.getClass());
063                            if (classDescriptor != null)
064                            {
065                                    Serializable id = persistenceService.getIdentifier(data, classDescriptor);
066    
067                                    if (LOG.isDebugEnabled())
068                                    {
069                                            LOG.debug("squeezing entity: " + data.toString());
070                                    }
071    
072                                    if (id == null)
073                                    {
074                                            return prefix + entityNameAbbreviator.abbreviate(classDescriptor.getType());
075                                    }
076    
077    //                      Serializable version = (Serializable) persistenceService.getVersion(data, classDescriptor);
078                                    return prefix + abbreviate(classDescriptor.getType()) + delimiter + next.squeeze(id);
079                            }
080                    }
081                    return next.squeeze(data);
082            }
083    
084            public String[] squeeze(Object[] objects, DataSqueezer next)
085            {
086                    final String[] squeezed = new String[objects.length];
087                    for (int i = 0; i < squeezed.length; i++)
088                    {
089                            squeezed[i] = squeeze(objects[i], next);
090                    }
091                    return squeezed;
092            }
093    
094            public Object unsqueeze(String string, DataSqueezer next)
095            {
096                    if (string.startsWith(prefix))
097                    {
098                            final String squeezed = string.substring(prefix.length());
099                            final int delimiterNdx = squeezed.indexOf(delimiter);
100    
101                            final String entityName;
102                            final Serializable id;
103    
104                            if (delimiterNdx > 0)
105                            {
106                                    entityName = squeezed.substring(0, delimiterNdx);
107                                    id = (Serializable) next.unsqueeze(squeezed.substring(delimiterNdx + delimiter.length()));
108                            } else
109                            {
110                                    entityName = squeezed;
111                                    id = null;
112                            }
113    
114                            final Class<?> clazz = (Class<?>) unabbreviate(entityName);
115    
116                            if (LOG.isDebugEnabled())
117                            {
118                                    LOG.debug("unsqueezing entity: " + clazz.getName() + " : " + id);
119                            }
120    
121                            if (id != null)
122                            {
123                                    return persistenceService.loadInstance(clazz, id);
124                            } else
125                            {
126                                    try
127                                    {
128                                            return builderDirector.createNewInstance(clazz);
129                                    } catch (TrailsRuntimeException e)
130                                    {
131                                            throw new ApplicationRuntimeException("decode-failure: unable to unsqueeze entity", e);
132                                    }
133                            }
134                    } else
135                    {
136                            return next.unsqueeze(string);
137                    }
138            }
139    
140            public Object[] unsqueeze(String[] strings, DataSqueezer next)
141            {
142                    final Object[] unsqueezed = new Object[strings.length];
143                    for (int i = 0; i < unsqueezed.length; i++)
144                    {
145                            unsqueezed[i] = unsqueeze(strings[i], next);
146                    }
147                    return unsqueezed;
148            }
149    
150            public void setDelimiter(String delimiter)
151            {
152                    this.delimiter = delimiter;
153            }
154    
155            public void setPrefix(String prefix)
156            {
157                    this.prefix = prefix;
158            }
159    
160            public void setDescriptorService(DescriptorService descriptorService)
161            {
162                    this.descriptorService = descriptorService;
163            }
164    
165            public void setPersistenceService(PersistenceService persistenceService)
166            {
167                    this.persistenceService = persistenceService;
168            }
169    
170            public void setEntityNameAbbreviator(EntityNameAbbreviator entityNameAbbreviator)
171            {
172                    this.entityNameAbbreviator = entityNameAbbreviator;
173                    shouldAbbreviate = entityNameAbbreviator != null;
174            }
175    
176            public void setBuilderDirector(BuilderDirector builderDirector)
177            {
178                    this.builderDirector = builderDirector;
179            }
180    
181            private String abbreviate(Class clazz)
182            {
183                    return shouldAbbreviate ? entityNameAbbreviator.abbreviate(clazz) : clazz.getName();
184            }
185    
186            private Class unabbreviate(String abbreviation)
187            {
188                    return shouldAbbreviate ? entityNameAbbreviator.unabbreviate(abbreviation) : Utils.classForName(abbreviation);
189            }
190    }