001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.form.j2ee;
042:
043: import java.awt.dnd.DnDConstants;
044: import java.awt.dnd.DropTargetDragEvent;
045: import java.util.*;
046: import java.util.logging.Level;
047: import java.util.logging.Logger;
048: import javax.swing.ImageIcon;
049: import javax.swing.text.JTextComponent;
050: import org.netbeans.api.db.explorer.DatabaseMetaDataTransfer;
051: import org.netbeans.api.project.FileOwnerQuery;
052: import org.netbeans.api.project.libraries.LibraryManager;
053: import org.netbeans.modules.form.BindingDesignSupport;
054: import org.netbeans.modules.form.BindingProperty;
055: import org.netbeans.modules.form.FormEditor;
056: import org.netbeans.modules.form.FormJavaSource;
057: import org.netbeans.modules.form.FormModel;
058: import org.netbeans.modules.form.MetaBinding;
059: import org.netbeans.modules.form.RADComponent;
060: import org.netbeans.modules.form.assistant.AssistantMessages;
061: import org.netbeans.modules.form.palette.PaletteItem;
062: import org.netbeans.modules.form.project.ClassPathUtils;
063: import org.netbeans.modules.form.project.ClassSource;
064: import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
065: import org.netbeans.modules.j2ee.persistence.api.metadata.orm.EntityMappingsMetadata;
066: import org.netbeans.modules.j2ee.persistence.api.PersistenceScope;
067: import org.netbeans.modules.j2ee.persistence.dd.persistence.model_1_0.PersistenceUnit;
068: import org.openide.filesystems.FileObject;
069: import org.openide.util.NbBundle;
070: import org.openide.util.Utilities;
071:
072: /**
073: * Result of database column DnD.
074: *
075: * @author Jan Stola
076: */
077: public class DBColumnDrop extends DBConnectionDrop {
078: /** Dropped column. */
079: private DatabaseMetaDataTransfer.Column column;
080:
081: /**
082: * Creates new <code>DBColumnDrop</code>.
083: *
084: * @param model form model.
085: * @param column dropped column.
086: */
087: public DBColumnDrop(FormModel model,
088: DatabaseMetaDataTransfer.Column column) {
089: super (model, null);
090: this .column = column;
091: }
092:
093: /**
094: * Returns <code>JTextField</code> palette item.
095: *
096: * @param dtde corresponding drop target drag event.
097: * @return <code>JTextField</code> palette item.
098: */
099: @Override
100: public PaletteItem getPaletteItem(DropTargetDragEvent dtde) {
101: PaletteItem pItem;
102: if (!assistantInitialized) {
103: initAssistant();
104: }
105: if (!J2EEUtils.hasPrimaryKey(column.getDatabaseConnection(),
106: column.getTableName())) {
107: FormEditor.getAssistantModel(model).setContext(
108: "tableWithoutPK"); // NOI18N
109: return null;
110: }
111: if (FormJavaSource.isInDefaultPackage(model)) {
112: // 97982: default package
113: FormEditor.getAssistantModel(model).setContext(
114: "columnDefaultPackage"); // NOI18N
115: return null;
116: }
117: setBindingOnly(dtde.getDropAction() == DnDConstants.ACTION_MOVE);
118: if (isBindingOnly()) {
119: FormEditor.getAssistantModel(model).setContext(
120: "columnDropBinding", "columnDropComponent"); // NOI18N
121: pItem = new PaletteItem(new ClassSource(
122: "javax.persistence.EntityManager", // NOI18N
123: new ClassSource.LibraryEntry(LibraryManager
124: .getDefault().getLibrary("toplink"))), // NOI18N
125: null);
126: pItem
127: .setIcon(new ImageIcon(
128: Utilities
129: .loadImage("org/netbeans/modules/form/j2ee/resources/binding.gif"))
130: .getImage()); // NOI18N
131: } else {
132: pItem = new PaletteItem(new ClassSource(
133: "javax.swing.JTextField"), null); // NOI18N
134: }
135: return pItem;
136: }
137:
138: /**
139: * Registers assistant messages related to DB column DnD.
140: */
141: private void initAssistant() {
142: ResourceBundle bundle = NbBundle.getBundle(DBColumnDrop.class);
143: String dropBindingMsg = bundle
144: .getString("MSG_ColumnDropBinding"); // NOI18N
145: String dropComponentMsg = bundle
146: .getString("MSG_ColumnDropComponent"); // NOI18N
147: String tableWithoutPKMsg = bundle
148: .getString("MSG_TableWithoutPK"); // NOI18N
149: String columnDefaultPackageMsg = bundle
150: .getString("MSG_ColumnDefaultPackage"); // NOI18N
151: AssistantMessages messages = AssistantMessages.getDefault();
152: messages.setMessages("columnDropBinding", dropBindingMsg); // NOI18N
153: messages.setMessages("columnDropComponent", dropComponentMsg); // NOI18N
154: messages.setMessages("tableWithoutPK", tableWithoutPKMsg); // NOI18N
155: messages.setMessages("columnDefaultPackage",
156: columnDefaultPackageMsg);
157: assistantInitialized = true;
158: }
159:
160: /**
161: * Post-processing after placement of the dragged column.
162: *
163: * @param componentId ID of the corresponding UI component.
164: * @param droppedOverId ID of a component the new component has been dropped over.
165: */
166: @Override
167: public void componentAdded(String componentId, String droppedOverId) {
168: try {
169: FileObject formFile = FormEditor.getFormDataObject(model)
170: .getFormFile();
171: project = FileOwnerQuery.getOwner(formFile);
172:
173: // Make sure persistence.xml file exists
174: FileObject persistenceXML = J2EEUtils.getPersistenceXML(
175: project, true);
176:
177: // Initializes persistence unit and persistence descriptor
178: PersistenceUnit unit = J2EEUtils.initPersistenceUnit(
179: persistenceXML, column.getDatabaseConnection());
180:
181: // Initializes project's classpath
182: J2EEUtils.updateProjectForUnit(persistenceXML, unit, column
183: .getJDBCDriver());
184:
185: // Obtain description of entity mappings
186: PersistenceScope scope = PersistenceScope
187: .getPersistenceScope(formFile);
188: MetadataModel<EntityMappingsMetadata> mappings = scope
189: .getEntityMappingsModel(unit.getName());
190:
191: // Find entity that corresponds to the dragged table
192: String[] entityInfo = J2EEUtils.findEntity(mappings, column
193: .getTableName());
194:
195: // Create a new entity (if there isn't one that corresponds to the dragged table)
196: if (entityInfo == null) {
197: // Generates a Java class for the entity
198: J2EEUtils.createEntity(formFile.getParent(), scope,
199: unit, column.getDatabaseConnection(), column
200: .getTableName(), null);
201:
202: entityInfo = J2EEUtils.findEntity(mappings, column
203: .getTableName());
204: } else {
205: // Add the entity into the persistence unit if it is not there already
206: J2EEUtils.addEntityToUnit(entityInfo[1], unit, project);
207: }
208:
209: J2EEUtils.makeEntityObservable(formFile, entityInfo,
210: mappings);
211:
212: // Find (or create) entity manager "bean" for the persistence unit
213: RADComponent entityManager;
214: if (isBindingOnly()) {
215: String unitName = unit.getName();
216: entityManager = J2EEUtils.findEntityManager(model,
217: unitName);
218: if (entityManager == null) {
219: entityManager = model.getMetaComponent(componentId);
220: entityManager.getPropertyByName("persistenceUnit")
221: .setValue(unitName); // NOI18N
222: J2EEUtils
223: .renameComponent(entityManager, true,
224: unitName + "EntityManager",
225: "entityManager"); // NOI18N
226: } else {
227: // The entity manager was already there => remove the dragged one
228: model.removeComponent(model
229: .getMetaComponent(componentId), true);
230: }
231: } else {
232: entityManager = initEntityManagerBean(unit);
233: }
234:
235: RADComponent control = null;
236: String controlProperty = null;
237: if (isBindingOnly()) {
238: if (droppedOverId == null)
239: return;
240: control = model.getMetaComponent(droppedOverId);
241: Class controlClass = control.getBeanClass();
242: controlProperty = controlProperty(controlClass);
243: if (controlProperty == null) {
244: return;
245: }
246: } else {
247: control = model.getMetaComponent(componentId);
248: controlProperty = "text"; // NOI18N
249: control.getPropertyByName("columns").setValue(15); // NOI18N
250: }
251:
252: List<String> l = Collections.singletonList(column
253: .getColumnName());
254: l = J2EEUtils.propertiesForColumns(mappings, entityInfo[0],
255: l);
256: if (l.isEmpty()) {
257: // There is no property corresponding to the dragged column
258: return;
259: }
260: String sourcePath = l.get(0);
261:
262: RADComponent metaTable = null;
263: for (RADComponent component : model.getAllComponents()) {
264: if ("java.util.List".equals(component.getBeanClass()
265: .getName())) { // NOI18N
266: Object value = component.getSyntheticProperty(
267: "typeParameters").getValue();
268: if (value instanceof String) {
269: int index = ((String) value)
270: .indexOf(entityInfo[1] + '>'); // PENDING improve this check
271: if (index != -1) {
272: for (RADComponent tableCand : model
273: .getAllComponents()) {
274: if (javax.swing.JTable.class
275: .isAssignableFrom(tableCand
276: .getBeanClass())) {
277: BindingProperty prop = tableCand
278: .getBindingProperty("elements"); // NOI18N
279: if (prop != null) {
280: MetaBinding binding = prop
281: .getValue();
282: if (binding.getSource() == component) {
283: metaTable = tableCand;
284: }
285: }
286: }
287: }
288: }
289: }
290: }
291: }
292:
293: BindingProperty prop;
294: MetaBinding binding;
295: if (metaTable == null) {
296: RADComponent metaEntity = null;
297: Class<?> entityClass = ClassPathUtils.loadClass(
298: entityInfo[1], formFile); // NOI18N
299: for (RADComponent component : model.getAllComponents()) {
300: if (entityClass.equals(component.getBeanClass())) {
301: metaEntity = component;
302: }
303: }
304:
305: if (metaEntity == null) {
306: RADComponent metaQuery = new RADComponent();
307: Class<?> queryClass = ClassPathUtils.loadClass(
308: "javax.persistence.Query", formFile); // NOI18N
309: metaQuery.initialize(model);
310: metaQuery.initInstance(queryClass);
311: metaQuery.getPropertyByName("entityManager")
312: .setValue(entityManager); // NOI18N
313: char c = entityInfo[0].toLowerCase().charAt(0);
314: String query = "SELECT " + c + " FROM "
315: + entityInfo[0] + " " + c; // NOI18N
316: metaQuery.getPropertyByName("query")
317: .setValue(query); // NOI18N
318: metaQuery.getPropertyByName("maxResults").setValue(
319: 1); // NOI18N
320: metaQuery.setStoredName(c
321: + entityInfo[0].substring(1) + "Query"); // NOI18N
322: model.addComponent(metaQuery, null, true);
323:
324: metaEntity = new RADComponent();
325: metaEntity.initialize(model);
326: metaEntity.initInstance(entityClass);
327: metaEntity.getPropertyByName("query").setValue(
328: metaQuery); // NOI18N
329: model.addComponent(metaEntity, null, true);
330: }
331:
332: prop = control.getBindingProperty(controlProperty); // NOI18N
333: binding = new MetaBinding(metaEntity,
334: BindingDesignSupport.elWrap(sourcePath),
335: control, controlProperty); // NOI18N
336: } else {
337: prop = control.getBindingProperty("enabled"); // NOI18N
338: binding = new MetaBinding(metaTable,
339: BindingDesignSupport
340: .elWrap("selectedElement != null"),
341: control, "enabled"); // NOI18N
342: prop.setValue(binding);
343: prop = control.getBindingProperty(controlProperty);
344: binding = new MetaBinding(metaTable,
345: BindingDesignSupport.elWrap("selectedElement."
346: + sourcePath), control, controlProperty); // NOI18N
347: if (controlProperty.equals("text")
348: && JTextComponent.class
349: .isAssignableFrom(control
350: .getBeanClass())) { // NOI18N
351: binding.setIncompletePathValueSpecified(true);
352: prop.getSubProperty(
353: BindingProperty.PROP_INCOMPLETE_VALUE)
354: .setValue(null);
355: }
356: }
357: prop.setValue(binding);
358: } catch (Exception ex) {
359: Logger.getLogger(getClass().getName()).log(Level.INFO,
360: ex.getMessage(), ex);
361: }
362: }
363:
364: /**
365: * Determines the property that should be bound.
366: *
367: * @param controlClass class of the control that will be bound.
368: * @return the name of the property that should be bound.
369: */
370: private static String controlProperty(Class controlClass) {
371: String controlProperty = null;
372: if (javax.swing.text.JTextComponent.class
373: .isAssignableFrom(controlClass)) {
374: controlProperty = "text"; // NOI18N
375: } else if (javax.swing.JToggleButton.class
376: .isAssignableFrom(controlClass)) {
377: controlProperty = "selected"; // NOI18N
378: } else if (javax.swing.JSlider.class
379: .isAssignableFrom(controlClass)) {
380: controlProperty = "value"; // NOI18N
381: }
382: return controlProperty;
383: }
384:
385: }
|