| /******************************************************************************* |
| * Copyright (c) 2008-2010 Sonatype, Inc. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Sonatype, Inc. - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.m2e.model.edit.pom.translators; |
| |
| import java.util.List; |
| |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Text; |
| |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; |
| import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; |
| |
| import org.eclipse.m2e.model.edit.pom.PomFactory; |
| import org.eclipse.m2e.model.edit.pom.PropertyElement; |
| |
| |
| /** |
| * Translates a property list using the name and value instead of reflection. |
| * |
| * @author Mike Poindexter |
| */ |
| public class PropertiesAdapter extends ListAdapter { |
| protected List<PropertyElement> properties; |
| |
| public PropertiesAdapter(SSESyncResource resc, Element containerNode, List<PropertyElement> properties) { |
| super(resc, containerNode, properties, null); |
| this.node = containerNode; |
| this.properties = properties; |
| } |
| |
| @Override |
| public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, |
| Object newValue, int pos) { |
| if(resource.isProcessEvents()) { |
| try { |
| resource.setProcessEvents(false); |
| if(INodeNotifier.ADD == eventType && newValue instanceof Element) { |
| if(notifier == node) { |
| IDOMElement addedElement = (IDOMElement) newValue; |
| int idx = absoluteIndexOf(node, addedElement); |
| if(idx == -1) |
| idx = 0; |
| properties.add(idx, createObject(addedElement)); |
| } |
| } else if(INodeNotifier.REMOVE == eventType && oldValue instanceof Element) { |
| if(notifier == node) { |
| for(PropertyElement prop : properties) { |
| PropertyChildAdapter adapter = (PropertyChildAdapter) EcoreUtil.getExistingAdapter(prop, |
| PropertyChildAdapter.class); |
| if(adapter.getElement().equals(oldValue)) { |
| properties.remove(prop); |
| break; |
| } |
| } |
| } |
| } else if(changedFeature instanceof Text) { |
| if(notifier != node && notifier instanceof Element) { |
| Element e = (Element) notifier; |
| String name = e.getLocalName(); |
| for(PropertyElement prop : properties) { |
| if(name.equals(prop.getName())) { |
| prop.setValue(getElementText(e)); |
| } |
| } |
| } |
| } |
| } finally { |
| resource.setProcessEvents(true); |
| } |
| |
| } |
| |
| } |
| |
| public void add(Object newValue, int position) { |
| final PropertyElement prop = (PropertyElement) newValue; |
| Element newElement = node.getOwnerDocument().createElement(prop.getName()); |
| Text value = node.getOwnerDocument().createTextNode(prop.getValue()); |
| newElement.appendChild(value); |
| |
| if(position < 0) |
| position = 0; |
| Node n = getNthChildWithName(node, "*", position); //$NON-NLS-1$ |
| if(n != null) { |
| node.insertBefore(newElement, n); |
| } else { |
| node.appendChild(newElement); |
| } |
| formatNode(newElement); |
| if(null == EcoreUtil.getExistingAdapter(prop, PropertyChildAdapter.class)) { |
| prop.eAdapters().add(new PropertyChildAdapter(prop, newElement)); |
| } |
| ((IDOMNode) newElement).addAdapter(this); |
| } |
| |
| public void remove(Object oldValue, int position) { |
| if(position == -1) |
| position = 0; |
| |
| Element n = getNthChildWithName(node, "*", position); //$NON-NLS-1$ |
| if(n != null) |
| removeChildElement(n); |
| } |
| |
| public PropertyElement createObject(Element child) { |
| PropertyElement propertyElement = PomFactory.eINSTANCE.createPropertyElement(); |
| propertyElement.setName(child.getLocalName()); |
| propertyElement.setValue(getElementText(child)); |
| if(null == ((IDOMNode) child).getExistingAdapter(PropertiesAdapter.class)) { |
| ((IDOMNode) child).addAdapter(this); |
| } |
| propertyElement.eAdapters().add(new PropertyChildAdapter(propertyElement, child)); |
| return propertyElement; |
| } |
| |
| @Override |
| public boolean isAdapterForType(Object type) { |
| return PropertiesAdapter.class.equals(type); |
| } |
| |
| @Override |
| public void load() { |
| //MNGECLIPSE-2345, MNGECLIPSE-2694 when load is called on a list adapter already containing items, |
| // the old items shall be discarded to avoid duplicates. |
| properties.clear(); |
| NodeList children = node.getChildNodes(); |
| int nChildren = children.getLength(); |
| for(int i = 0; i < nChildren; i++ ) { |
| Node child = children.item(i); |
| if(child instanceof Element) { |
| properties.add(createObject((Element) child)); |
| } |
| |
| } |
| |
| } |
| |
| @Override |
| public void save() { |
| for(PropertyElement o : properties) { |
| add(o, -1); |
| } |
| } |
| |
| private class PropertyChildAdapter implements Adapter { |
| private Notifier target; |
| |
| private PropertyElement property; |
| |
| private Element element; |
| |
| /** |
| * @param propertyElement |
| * @param container |
| */ |
| public PropertyChildAdapter(PropertyElement propertyElement, Element element) { |
| super(); |
| this.property = propertyElement; |
| this.element = element; |
| } |
| |
| public boolean isAdapterForType(Object type) { |
| return PropertyChildAdapter.class.equals(type); |
| } |
| |
| public void notifyChanged(Notification notification) { |
| if(resource.isProcessEvents()) { |
| try { |
| resource.setProcessEvents(false); |
| Element newElement = node.getOwnerDocument().createElement(property.getName()); |
| Text value = node.getOwnerDocument().createTextNode(property.getValue()); |
| newElement.appendChild(value); |
| node.replaceChild(newElement, element); |
| formatNode(newElement); |
| this.element = newElement; |
| ((IDOMNode) newElement).addAdapter(PropertiesAdapter.this); |
| } finally { |
| resource.setProcessEvents(true); |
| } |
| } |
| } |
| |
| /** |
| * @return the target |
| */ |
| public Notifier getTarget() { |
| return target; |
| } |
| |
| /** |
| * @param target the target to set |
| */ |
| public void setTarget(Notifier target) { |
| this.target = target; |
| } |
| |
| /** |
| * @return the property |
| */ |
| public PropertyElement getProperty() { |
| return property; |
| } |
| |
| /** |
| * @return the element |
| */ |
| public Element getElement() { |
| return element; |
| } |
| |
| } |
| |
| } |