1 |
| package photospace.web.spring; |
2 |
| |
3 |
| import java.awt.image.*; |
4 |
| import java.io.*; |
5 |
| import java.text.*; |
6 |
| import java.util.*; |
7 |
| import javax.servlet.http.*; |
8 |
| import org.apache.commons.collections.*; |
9 |
| import org.apache.commons.lang.*; |
10 |
| import org.apache.commons.logging.*; |
11 |
| import org.springframework.beans.*; |
12 |
| import org.springframework.beans.propertyeditors.*; |
13 |
| import org.springframework.validation.*; |
14 |
| import org.springframework.web.bind.*; |
15 |
| import org.springframework.web.servlet.*; |
16 |
| import org.springframework.web.servlet.mvc.*; |
17 |
| import photospace.beans.*; |
18 |
| import photospace.graphics.*; |
19 |
| import photospace.meta.*; |
20 |
| import photospace.vfs.*; |
21 |
| import photospace.search.*; |
22 |
| |
23 |
| public class EditController |
24 |
| extends AbstractFormController |
25 |
| { |
26 |
| private static final Log log = LogFactory.getLog(EditController.class); |
27 |
| |
28 |
| private Persister persister; |
29 |
| private Searcher searcher; |
30 |
| private FileSystem filesystem; |
31 |
| private List multiEditProperties = Arrays.asList(new String[] { "title", |
32 |
| "description", |
33 |
| "creator", |
34 |
| "created", |
35 |
| "position.latitude", |
36 |
| "position.longitude" |
37 |
| }); |
38 |
| |
39 |
1
| public EditController()
|
40 |
| { |
41 |
1
| setSessionForm(true);
|
42 |
1
| setBindOnNewForm(false);
|
43 |
| } |
44 |
| |
45 |
1
| protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder)
|
46 |
| throws Exception |
47 |
| { |
48 |
1
| binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, new DecimalFormat("##0.000000"), true));
|
49 |
1
| binder.registerCustomEditor(Date.class, new DateEditor(new SimpleDateFormat(getMessageSourceAccessor().getMessage("format.dateTime")), true));
|
50 |
1
| binder.registerCustomEditor(String[].class, "meta.labels", new LabelsEditor());
|
51 |
| } |
52 |
| |
53 |
1
| protected Object formBackingObject(HttpServletRequest request) throws Exception
|
54 |
| { |
55 |
1
| String[] paths = request.getParameterValues("paths");
|
56 |
1
| if (paths != null)
|
57 |
| { |
58 |
1
| EditCommand command = new EditCommand(new Meta());
|
59 |
1
| command.setPaths(paths);
|
60 |
| |
61 |
1
| List metas = new ArrayList();
|
62 |
1
| for (int i = 0; i < command.getPaths().length; i++)
|
63 |
| { |
64 |
2
| Meta meta = persister.getMeta(command.getPaths()[i]);
|
65 |
2
| if (meta instanceof FolderMeta)
|
66 |
| { |
67 |
0
| FolderMeta folder = (FolderMeta) searcher.browse(meta.getPath(), Searcher.PHOTO_CONSTRAINT, Searcher.ASCENDING, 0, 3);
|
68 |
0
| ((FolderMeta) meta).addFiles(folder.getFiles());
|
69 |
| } |
70 |
2
| metas.add(meta);
|
71 |
| } |
72 |
1
| command.setMetas(metas);
|
73 |
1
| BeanWrapper wrapper = new BeanWrapperImpl(command.getMeta());
|
74 |
1
| for (Iterator p = multiEditProperties.iterator(); p.hasNext();)
|
75 |
| { |
76 |
6
| setSharedValue(wrapper, metas, (String) p.next());
|
77 |
| } |
78 |
1
| command.setSharedKeywords(getSharedKeywords(metas));
|
79 |
1
| command.getMeta().setLabels((String[]) command.getSharedKeywords().toArray(new String[] {}));
|
80 |
1
| return command;
|
81 |
| } |
82 |
0
| throw new ServletRequestBindingException("Required parameter 'paths' was not supplied");
|
83 |
| } |
84 |
| |
85 |
1
| private Set getSharedKeywords(List metas)
|
86 |
| { |
87 |
1
| HashSet shared = new HashSet(Arrays.asList(((Meta) metas.get(0)).getLabels()));
|
88 |
1
| for (Iterator labels = metas.iterator(); labels.hasNext();)
|
89 |
| { |
90 |
2
| Meta meta = (Meta) labels.next();
|
91 |
2
| shared.retainAll(Arrays.asList(meta.getLabels()));
|
92 |
| } |
93 |
1
| return shared;
|
94 |
| } |
95 |
| |
96 |
0
| protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response,
|
97 |
| Object command, BindException errors) throws Exception |
98 |
| { |
99 |
0
| if (errors.hasErrors())
|
100 |
| { |
101 |
0
| logger.debug("Data binding errors: " + errors.getErrorCount());
|
102 |
0
| return showForm(request, response, errors);
|
103 |
| } |
104 |
| else |
105 |
| { |
106 |
0
| logger.debug("No errors -> processing submit");
|
107 |
0
| return onSubmit(request, response, command, errors);
|
108 |
| } |
109 |
| } |
110 |
| |
111 |
0
| protected ModelAndView showForm(HttpServletRequest request, HttpServletResponse response,
|
112 |
| BindException errors) throws Exception |
113 |
| { |
114 |
0
| if (isSessionForm()) request.getSession().setAttribute(getFormSessionAttributeName(), errors.getTarget());
|
115 |
0
| return new ModelAndView("/edit", errors.getModel());
|
116 |
| } |
117 |
| |
118 |
6
| private void setSharedValue(BeanWrapper bean, List metas, String property)
|
119 |
| { |
120 |
6
| Set values = new HashSet();
|
121 |
6
| CollectionUtils.collect(metas, new PropertyTransformer(property), values);
|
122 |
6
| if (values.size() == 1) bean.setPropertyValue(property, values.iterator().next());
|
123 |
| } |
124 |
| |
125 |
1
| protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception
|
126 |
| { |
127 |
1
| EditCommand form = (EditCommand) command;
|
128 |
1
| if (!StringUtils.isEmpty(form.getRotate()))
|
129 |
| { |
130 |
0
| int degrees = 0;
|
131 |
0
| if ("left".equals(form.getRotate())) degrees = -90;
|
132 |
0
| if ("right".equals(form.getRotate())) degrees = 90;
|
133 |
0
| log.debug("Rotating " + Arrays.asList(form.getPaths()) + " " + form.getRotate());
|
134 |
0
| for (Iterator i = form.getMetas().iterator(); i.hasNext();)
|
135 |
| { |
136 |
0
| Meta meta = (Meta) i.next();
|
137 |
0
| if (! (meta instanceof PhotoMeta)) continue;
|
138 |
0
| File file = filesystem.getFile(meta.getPath());
|
139 |
0
| try
|
140 |
| { |
141 |
0
| BufferedImage image = Sampler.read(file);
|
142 |
0
| Sampler.write(Sampler.rotate(image, degrees), file);
|
143 |
| } |
144 |
| catch (IOException e) |
145 |
| { |
146 |
0
| log.warn("Exception rotation " + meta, e);
|
147 |
0
| request.setAttribute("error", getMessageSourceAccessor().getMessage("error.rotate.failed",
|
148 |
| new Object[] { meta.getLabel() })); |
149 |
0
| break;
|
150 |
| } |
151 |
| } |
152 |
0
| form.setRotate(null);
|
153 |
| } |
154 |
| else |
155 |
| { |
156 |
1
| log.debug("Editing " + Arrays.asList(form.getPaths()));
|
157 |
1
| BeanWrapper edited = new BeanWrapperImpl(form.getMeta());
|
158 |
1
| for (Iterator i = form.getMetas().iterator(); i.hasNext();)
|
159 |
| { |
160 |
2
| Meta meta = (Meta) i.next();
|
161 |
2
| BeanWrapper bean = new BeanWrapperImpl(meta);
|
162 |
2
| for (Iterator p = multiEditProperties.iterator(); p.hasNext();)
|
163 |
| { |
164 |
12
| String property = (String) p.next();
|
165 |
12
| Object value = edited.getPropertyValue(property);
|
166 |
0
| if (!form.isMultiEdit()) bean.setPropertyValue(property, value);
|
167 |
6
| else if (value == null || (value instanceof String && StringUtils.isEmpty((String) value))) continue;
|
168 |
6
| else bean.setPropertyValue(property, value);
|
169 |
| } |
170 |
2
| if (form.isMultiEdit())
|
171 |
| { |
172 |
2
| List labels = new ArrayList(Arrays.asList(meta.getLabels()));
|
173 |
2
| labels.removeAll(form.getRemovedKeywords());
|
174 |
2
| labels.addAll(Arrays.asList(form.getMeta().getLabels()));
|
175 |
2
| meta.setLabels((String[]) labels.toArray(new String[] {}));
|
176 |
| } |
177 |
| else |
178 |
| { |
179 |
0
| meta.setLabels(form.getMeta().getLabels());
|
180 |
| } |
181 |
| |
182 |
2
| persister.saveMeta(meta.getPath(), meta);
|
183 |
| } |
184 |
| } |
185 |
| |
186 |
1
| request.setAttribute("message", getMessageSourceAccessor().getMessage("message.edit.success"));
|
187 |
| |
188 |
1
| return new ModelAndView("/edit", errors.getModel());
|
189 |
| } |
190 |
| |
191 |
1
| public void setPersister(Persister persister)
|
192 |
| { |
193 |
1
| this.persister = persister;
|
194 |
| } |
195 |
| |
196 |
1
| public void setFilesystem(FileSystem filesystem)
|
197 |
| { |
198 |
1
| this.filesystem = filesystem;
|
199 |
| } |
200 |
| |
201 |
1
| public void setSearcher(Searcher searcher)
|
202 |
| { |
203 |
1
| this.searcher = searcher;
|
204 |
| } |
205 |
| } |