View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
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.argeo.cms.ui.workbench.internal.jcr.parts;
17  
18  import java.text.DateFormat;
19  import java.text.SimpleDateFormat;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.List;
23  import java.util.ListIterator;
24  
25  import javax.jcr.Node;
26  import javax.jcr.Property;
27  import javax.jcr.PropertyIterator;
28  import javax.jcr.PropertyType;
29  import javax.jcr.RepositoryException;
30  
31  import org.argeo.cms.ui.CmsConstants;
32  import org.argeo.cms.ui.workbench.internal.WorkbenchConstants;
33  import org.argeo.eclipse.ui.EclipseUiException;
34  import org.argeo.jcr.JcrUtils;
35  import org.eclipse.swt.SWT;
36  import org.eclipse.swt.events.ModifyEvent;
37  import org.eclipse.swt.events.ModifyListener;
38  import org.eclipse.swt.layout.GridData;
39  import org.eclipse.swt.layout.GridLayout;
40  import org.eclipse.swt.widgets.Composite;
41  import org.eclipse.swt.widgets.Control;
42  import org.eclipse.swt.widgets.Text;
43  import org.eclipse.ui.forms.AbstractFormPart;
44  import org.eclipse.ui.forms.IManagedForm;
45  import org.eclipse.ui.forms.editor.FormEditor;
46  import org.eclipse.ui.forms.editor.FormPage;
47  import org.eclipse.ui.forms.widgets.FormToolkit;
48  import org.eclipse.ui.forms.widgets.ScrolledForm;
49  
50  /**
51   * Work-In-Progress Node editor page: provides edition feature on String
52   * properties for power users. TODO implement manual modification of all
53   * property types.
54   */
55  
56  public class GenericNodePage extends FormPage implements WorkbenchConstants {
57  	// private final static Log log = LogFactory.getLog(GenericNodePage.class);
58  
59  	// local constants
60  	private final static String JCR_PROPERTY_NAME = "jcr:name";
61  
62  	// Utils
63  	protected DateFormat timeFormatter = new SimpleDateFormat(CmsConstants.DATE_TIME_FORMAT);
64  
65  	// Main business Objects
66  	private Node currentNode;
67  
68  	// This page widgets
69  	private FormToolkit tk;
70  	private List<Control> modifyableProperties = new ArrayList<Control>();
71  
72  	public GenericNodePage(FormEditor editor, String title, Node currentNode) {
73  		super(editor, "id", title);
74  		this.currentNode = currentNode;
75  	}
76  
77  	protected void createFormContent(IManagedForm managedForm) {
78  		tk = managedForm.getToolkit();
79  		ScrolledForm form = managedForm.getForm();
80  		Composite innerBox = form.getBody();
81  		// Composite innerBox = new Composite(form.getBody(), SWT.NO_FOCUS);
82  		GridLayout twt = new GridLayout(3, false);
83  		innerBox.setLayout(twt);
84  		createPropertiesPart(innerBox);
85  	}
86  
87  	private void createPropertiesPart(Composite parent) {
88  		try {
89  			AbstractFormPart part = new AbstractFormPart() {
90  				public void commit(boolean onSave) {
91  					try {
92  						if (onSave) {
93  							ListIterator<Control> it = modifyableProperties.listIterator();
94  							while (it.hasNext()) {
95  								// we only support Text controls
96  								Text curControl = (Text) it.next();
97  								String value = curControl.getText();
98  								currentNode.setProperty((String) curControl.getData(JCR_PROPERTY_NAME), value);
99  							}
100 
101 							// We only commit when onSave = true,
102 							// thus it is still possible to save after a tab
103 							// change.
104 							if (currentNode.getSession().hasPendingChanges())
105 								currentNode.getSession().save();
106 							super.commit(onSave);
107 						}
108 					} catch (RepositoryException re) {
109 						throw new EclipseUiException("Cannot save properties on " + currentNode, re);
110 					}
111 				}
112 			};
113 
114 			PropertyIterator pi = currentNode.getProperties();
115 			while (pi.hasNext()) {
116 				Property prop = pi.nextProperty();
117 				addPropertyLine(parent, part, prop);
118 			}
119 			getManagedForm().addPart(part);
120 		} catch (RepositoryException re) {
121 			throw new EclipseUiException("Cannot display properties for " + currentNode, re);
122 		}
123 	}
124 
125 	private void addPropertyLine(Composite parent, AbstractFormPart part, Property prop) {
126 		try {
127 			tk.createLabel(parent, prop.getName());
128 			tk.createLabel(parent, "[" + JcrUtils.getPropertyDefinitionAsString(prop) + "]");
129 
130 			if (prop.getDefinition().isProtected()) {
131 				tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
132 			} else
133 				addModifyableValueWidget(parent, part, prop);
134 		} catch (RepositoryException re) {
135 			throw new EclipseUiException("Cannot display property " + prop, re);
136 		}
137 	}
138 
139 	private String formatReadOnlyPropertyValue(Property prop) throws RepositoryException {
140 		String strValue;
141 		if (prop.getType() == PropertyType.BINARY)
142 			strValue = "<binary>";
143 		else if (prop.isMultiple())
144 			strValue = Arrays.asList(prop.getValues()).toString();
145 		else if (prop.getType() == PropertyType.DATE)
146 			strValue = timeFormatter.format(prop.getValue().getDate().getTime());
147 		else
148 			strValue = prop.getValue().getString();
149 		return strValue;
150 	}
151 
152 	private Control addModifyableValueWidget(Composite parent, AbstractFormPart part, Property prop)
153 			throws RepositoryException {
154 		GridData gd;
155 		if (prop.getType() == PropertyType.STRING && !prop.isMultiple()) {
156 			Text txt = tk.createText(parent, prop.getString(), SWT.WRAP | SWT.MULTI);
157 			gd = new GridData(GridData.FILL_HORIZONTAL);
158 			txt.setLayoutData(gd);
159 			txt.addModifyListener(new ModifiedFieldListener(part));
160 			txt.setData(JCR_PROPERTY_NAME, prop.getName());
161 			modifyableProperties.add(txt);
162 		} else {
163 			// unsupported property type for editing, we create a read only
164 			// label.
165 			return tk.createLabel(parent, formatReadOnlyPropertyValue(prop));
166 		}
167 		return null;
168 	}
169 
170 	private class ModifiedFieldListener implements ModifyListener {
171 		private static final long serialVersionUID = 2117484480773434646L;
172 		private AbstractFormPart formPart;
173 
174 		public ModifiedFieldListener(AbstractFormPart generalPart) {
175 			this.formPart = generalPart;
176 		}
177 
178 		public void modifyText(ModifyEvent e) {
179 			formPart.markDirty();
180 		}
181 	}
182 }