diff --git a/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF index 0fd771831eb..ade9b1f75bf 100644 --- a/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF @@ -2,17 +2,11 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.e4.emf.xpath -Bundle-Version: 0.5.100.qualifier +Bundle-Version: 0.6.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.emf.ecore;bundle-version="2.35.0", - org.eclipse.core.runtime;bundle-version="3.29.0" -Export-Package: org.eclipse.e4.emf.internal.xpath;x-internal:=true, - org.eclipse.e4.emf.internal.xpath.helper;x-friends:="org.eclipse.e4.emf.xpath.test,org.eclipse.e4.ui.model.workbench,org.eclipse.e4.ui.workbench", - org.eclipse.e4.emf.xpath -Import-Package: org.apache.commons.jxpath;version="[1.3.0,2.0.0)", - org.apache.commons.jxpath.ri;version="[1.3.0,2.0.0)", - org.apache.commons.jxpath.ri.compiler;version="[1.3.0,2.0.0)", - org.apache.commons.jxpath.ri.model;version="[1.3.0,2.0.0)", - org.apache.commons.jxpath.util;version="[1.3.0,2.0.0)" + org.eclipse.core.runtime;bundle-version="3.29.0", + org.eclipse.emf.ecore.xmi;bundle-version="2.38.0" +Export-Package: org.eclipse.e4.emf.xpath Bundle-Vendor: %Bundle-Vendor Automatic-Module-Name: org.eclipse.e4.emf.xpath diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionAttributeNodeIterator.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionAttributeNodeIterator.java deleted file mode 100644 index 519d6f0dca6..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionAttributeNodeIterator.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodeIterator; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * Combines attribute node iterators of all elements of a collection into one - * aggregate attribute node iterator. - */ -public class CollectionAttributeNodeIterator extends CollectionNodeIterator { - - private QName name; - - /** - * Create a new CollectionAttributeNodeIterator. - * @param pointer collection pointer - * @param name attribute name - */ - public CollectionAttributeNodeIterator( - CollectionPointer pointer, - QName name) { - super(pointer, false, null); - this.name = name; - } - - @Override - protected NodeIterator getElementNodeIterator(NodePointer elementPointer) { - return elementPointer.attributeIterator(name); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionChildNodeIterator.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionChildNodeIterator.java deleted file mode 100644 index 84f168155fc..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionChildNodeIterator.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.ri.compiler.NodeTest; -import org.apache.commons.jxpath.ri.model.NodeIterator; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * Combines child node iterators of all elements of a collection into one - * aggregate child node iterator. - */ -public class CollectionChildNodeIterator extends CollectionNodeIterator { - - private NodeTest test; - - /** - * Create a new CollectionChildNodeIterator. - * @param pointer CollectionPointer - * @param test child test - * @param reverse iteration order - * @param startWith starting pointer - */ - public CollectionChildNodeIterator( - CollectionPointer pointer, - NodeTest test, - boolean reverse, - NodePointer startWith) { - super(pointer, reverse, startWith); - this.test = test; - } - - @Override - protected NodeIterator getElementNodeIterator(NodePointer elementPointer) { - return elementPointer.childIterator(test, false, null); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionNodeIterator.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionNodeIterator.java deleted file mode 100644 index 9b85feaee8a..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionNodeIterator.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.jxpath.JXPathException; -import org.apache.commons.jxpath.ri.model.NodeIterator; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * Combines node iterators of all elements of a collection into one - * aggregate node iterator. - */ -public abstract class CollectionNodeIterator implements NodeIterator { - private CollectionPointer pointer; - private boolean reverse; - private NodePointer startWith; - private int position; - private List collection; - - /** - * Create a new CollectionNodeIterator. - * @param pointer collection pointer - * @param reverse iteration order - * @param startWith starting pointer - */ - protected CollectionNodeIterator( - CollectionPointer pointer, - boolean reverse, - NodePointer startWith) { - this.pointer = pointer; - this.reverse = reverse; - this.startWith = startWith; - } - - /** - * Implemented by subclasses to produce child/attribute node iterators. - * @param elementPointer owning pointer - * @return NodeIterator - */ - protected abstract NodeIterator - getElementNodeIterator(NodePointer elementPointer); - - @Override - public int getPosition() { - return position; - } - - @Override - public boolean setPosition(int position) { - if (collection == null) { - prepare(); - } - - if (position < 1 || position > collection.size()) { - return false; - } - this.position = position; - return true; - } - - @Override - public NodePointer getNodePointer() { - if (position == 0) { - return null; - } - return (NodePointer) collection.get(position - 1); - } - - /** - * Prepare... - */ - private void prepare() { - collection = new ArrayList<>(); - NodePointer ptr = (NodePointer) pointer.clone(); - int length = ptr.getLength(); - for (int i = 0; i < length; i++) { - ptr.setIndex(i); - NodePointer elementPointer = ptr.getValuePointer(); - NodeIterator iter = getElementNodeIterator(elementPointer); - - for (int j = 1; iter.setPosition(j); j++) { - NodePointer childPointer = iter.getNodePointer(); - if (reverse) { - collection.add(0, childPointer); - } - else { - collection.add(childPointer); - } - } - } - if (startWith != null) { - int index = collection.indexOf(startWith); - if (index == -1) { - throw new JXPathException( - "Invalid starting pointer for iterator: " + startWith); - } - while (collection.size() > index) { - if (!reverse) { - collection.remove(collection.size() - 1); - } - else { - collection.remove(0); - } - } - } - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionPointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionPointer.java deleted file mode 100644 index ed3ee924e85..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/CollectionPointer.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Locale; - -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.JXPathIntrospector; -import org.apache.commons.jxpath.ri.Compiler; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.compiler.NodeNameTest; -import org.apache.commons.jxpath.ri.compiler.NodeTest; -import org.apache.commons.jxpath.ri.compiler.NodeTypeTest; -import org.apache.commons.jxpath.ri.model.NodeIterator; -import org.apache.commons.jxpath.ri.model.NodePointer; -import org.eclipse.e4.emf.internal.xpath.helper.ValueUtils; - -/** - * Transparent pointer to a collection (array or Collection). - */ -public class CollectionPointer extends NodePointer { - private Object collection; - private NodePointer valuePointer; - - private static final long serialVersionUID = 8620254915563256588L; - - /** - * Create a new CollectionPointer. - * @param collection value - * @param locale Locale - */ - public CollectionPointer(Object collection, Locale locale) { - super(null, locale); - this.collection = collection; - } - - /** - * Create a new CollectionPointer. - * @param parent parent NodePointer - * @param collection value - */ - public CollectionPointer(NodePointer parent, Object collection) { - super(parent); - this.collection = collection; - } - - @Override - public QName getName() { - return null; - } - - @Override - public Object getBaseValue() { - return collection; - } - - @Override - public boolean isCollection() { - return true; - } - - @Override - public int getLength() { - return ValueUtils.getLength(getBaseValue()); - } - - @Override - public boolean isLeaf() { - Object value = getNode(); - return value == null || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic(); - } - - @Override - public boolean isContainer() { - return index != WHOLE_COLLECTION; - } - - @Override - public Object getImmediateNode() { - return index == WHOLE_COLLECTION ? ValueUtils.getValue(collection) - : ValueUtils.getValue(collection, index); - } - - @Override - public void setValue(Object value) { - if (index == WHOLE_COLLECTION) { - parent.setValue(value); - } - else { - ValueUtils.setValue(collection, index, value); - } - } - - @Override - public void setIndex(int index) { - super.setIndex(index); - valuePointer = null; - } - - @Override - public NodePointer getValuePointer() { - if (valuePointer == null) { - if (index == WHOLE_COLLECTION) { - valuePointer = this; - } - else { - Object value = getImmediateNode(); - valuePointer = - NodePointer.newChildNodePointer(this, getName(), value); - } - } - return valuePointer; - } - - @Override - public NodePointer createPath(JXPathContext context) { - if (ValueUtils.getLength(getBaseValue()) <= index) { - collection = ValueUtils.expandCollection(getNode(), index + 1); - } - return this; - } - - @Override - public NodePointer createPath(JXPathContext context, Object value) { - NodePointer ptr = createPath(context); - ptr.setValue(value); - return ptr; - } - - @Override - public NodePointer createChild( - JXPathContext context, - QName name, - int index, - Object value) { - NodePointer ptr = (NodePointer) clone(); - ptr.setIndex(index); - return ptr.createPath(context, value); - } - - @Override - public NodePointer createChild( - JXPathContext context, - QName name, - int index) { - NodePointer ptr = (NodePointer) clone(); - ptr.setIndex(index); - return ptr.createPath(context); - } - - @Override - public int hashCode() { - return System.identityHashCode(collection) + index; - } - - @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - - if (!(object instanceof CollectionPointer)) { - return false; - } - - CollectionPointer other = (CollectionPointer) object; - return collection == other.collection && index == other.index; - } - - @Override - public NodeIterator childIterator(NodeTest test, - boolean reverse, NodePointer startWith) { - if (index == WHOLE_COLLECTION) { - return new CollectionChildNodeIterator( - this, - test, - reverse, - startWith); - } - return getValuePointer().childIterator(test, reverse, startWith); - } - - @Override - public NodeIterator attributeIterator(QName name) { - return index == WHOLE_COLLECTION ? new CollectionAttributeNodeIterator(this, name) - : getValuePointer().attributeIterator(name); - } - - @Override - public NodeIterator namespaceIterator() { - return index == WHOLE_COLLECTION ? null : getValuePointer().namespaceIterator(); - } - - @Override - public NodePointer namespacePointer(String namespace) { - return index == WHOLE_COLLECTION ? null : getValuePointer().namespacePointer(namespace); - } - - @Override - public boolean testNode(NodeTest test) { - if (index == WHOLE_COLLECTION) { - if (test == null) { - return true; - } - if (test instanceof NodeNameTest) { - return false; - } - return test instanceof NodeTypeTest && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_NODE; - } - return getValuePointer().testNode(test); - } - - @Override - public int compareChildNodePointers( - NodePointer pointer1, NodePointer pointer2) { - return pointer1.getIndex() - pointer2.getIndex(); - } - - @Override - public String asPath() { - StringBuilder buffer = new StringBuilder(); - NodePointer parent = getImmediateParentPointer(); - if (parent != null) { - buffer.append(parent.asPath()); - if (index != WHOLE_COLLECTION) { - // Address the list[1][2] case - if (parent.getIndex() != WHOLE_COLLECTION) { - buffer.append("/."); - } - buffer.append("[").append(index + 1).append(']'); - } - } else if (index != WHOLE_COLLECTION) { - buffer.append("/.[").append(index + 1).append(']'); - } - else { - buffer.append("/"); - } - return buffer.toString(); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectAttributeIterator.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectAttributeIterator.java deleted file mode 100644 index f57fca40496..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectAttributeIterator.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * An iterator of attributes of a JavaBean. Returns bean properties as - * well as the "xml:lang" attribute. - */ -public class EObjectAttributeIterator extends EStructuralFeatureIterator { - private NodePointer parent; - private int position = 0; - private boolean includeXmlLang; - - /** - * Create a new BeanAttributeIterator. - * @param parent parent pointer - * @param name name of this bean - */ - public EObjectAttributeIterator(EStructuralFeatureOwnerPointer parent, QName name) { - super( - parent, - (name.getPrefix() == null - && (name.getName() == null || name.getName().equals("*"))) - ? null - : name.toString(), - false, - null); - this.parent = parent; - includeXmlLang = - (name.getPrefix() != null && name.getPrefix().equals("xml")) - && (name.getName().equals("lang") - || name.getName().equals("*")); - } - - @Override - public NodePointer getNodePointer() { - return includeXmlLang && position == 1 ? new LangAttributePointer(parent) : super.getNodePointer(); - } - - @Override - public int getPosition() { - return position; - } - - @Override - public boolean setPosition(int position) { - this.position = position; - if (includeXmlLang) { - return position == 1 || super.setPosition(position - 1); - } - return super.setPosition(position); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPointer.java deleted file mode 100644 index 4e3db5ea878..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPointer.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Locale; -import java.util.Objects; - -import org.apache.commons.jxpath.JXPathIntrospector; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; -import org.eclipse.e4.emf.internal.xpath.helper.JXPathEObjectInfo; - -/** - * A Pointer that points to a JavaBean or a collection. It is either - * the first element of a path or a pointer for a property value. - * Typically there is a {@link EObjectPropertyPointer} between two EObjectPointers - * in the chain. - */ -public class EObjectPointer extends EStructuralFeatureOwnerPointer { - private QName name; - private Object bean; - private JXPathEObjectInfo beanInfo; - - private static final long serialVersionUID = -8227317938284982440L; - - /** - * Create a new BeanPointer. - * @param name is the name given to the first node - * @param bean pointed - * @param beanInfo JXPathBeanInfo - * @param locale Locale - */ - public EObjectPointer(QName name, Object bean, JXPathEObjectInfo beanInfo, - Locale locale) { - super(null, locale); - this.name = name; - this.bean = bean; - this.beanInfo = beanInfo; - } - - /** - * Create a new BeanPointer. - * @param parent pointer - * @param name is the name given to the first node - * @param bean pointed - * @param beanInfo JXPathBeanInfo - */ - public EObjectPointer(NodePointer parent, QName name, Object bean, - JXPathEObjectInfo beanInfo) { - super(parent); - this.name = name; - this.bean = bean; - this.beanInfo = beanInfo; - } - - @Override - public EStructuralFeaturePointer getPropertyPointer() { - return new EObjectPropertyPointer(this, beanInfo); - } - - @Override - public QName getName() { - return name; - } - - @Override - public Object getBaseValue() { - return bean; - } - - /** - * {@inheritDoc} - * @return false - */ - @Override - public boolean isCollection() { - return false; - } - - /** - * {@inheritDoc} - * @return 1 - */ - @Override - public int getLength() { - return 1; - } - - @Override - public boolean isLeaf() { - Object value = getNode(); - return value == null - || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic(); - } - - @Override - public int hashCode() { - return Objects.hashCode(name); - } - - @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - - if (!(object instanceof EObjectPointer)) { - return false; - } - - EObjectPointer other = (EObjectPointer) object; - if (!Objects.equals(parent, other.parent)) { - return false; - } - - if (!Objects.equals(name, other.name)) { - return false; - } - - int iThis = (index == WHOLE_COLLECTION ? 0 : index); - int iOther = (other.index == WHOLE_COLLECTION ? 0 : other.index); - if (iThis != iOther) { - return false; - } - - if (bean instanceof Number - || bean instanceof String - || bean instanceof Boolean) { - return bean.equals(other.bean); - } - return bean == other.bean; - } - - /** - * {@inheritDoc} - * If the pointer has a parent, then parent's path. - * If the bean is null, "null()". - * If the bean is a primitive value, the value itself. - * Otherwise - an empty string. - */ - @Override - public String asPath() { - if (parent != null) { - return super.asPath(); - } - if (bean == null) { - return "null()"; - } - if (bean instanceof Number) { - String string = bean.toString(); - if (string.endsWith(".0")) { - string = string.substring(0, string.length() - 2); - } - return string; - } - if (bean instanceof Boolean) { - return ((Boolean) bean).booleanValue() ? "true()" : "false()"; - } - if (bean instanceof String) { - return "'" + bean + "'"; - } - return "/"; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPointerFactory.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPointerFactory.java deleted file mode 100644 index 841aab4eaad..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPointerFactory.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Locale; - -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; -import org.apache.commons.jxpath.ri.model.NodePointerFactory; -import org.eclipse.e4.emf.internal.xpath.helper.JXPathEObjectInfo; -import org.eclipse.emf.ecore.EObject; - -/** - * Implements NodePointerFactory for JavaBeans. - */ -public class EObjectPointerFactory implements NodePointerFactory { - - /** factory order constant */ - public static final int BEAN_POINTER_FACTORY_ORDER = 900; - - @Override - public int getOrder() { - return BEAN_POINTER_FACTORY_ORDER; - } - - @Override - public NodePointer createNodePointer(QName name, Object bean, Locale locale) { - JXPathEObjectInfo bi = new JXPathEObjectInfo(((EObject)bean).eClass()); - return new EObjectPointer(name, bean, bi, locale); - } - - @Override - public NodePointer createNodePointer(NodePointer parent, QName name, - Object bean) { - if (bean == null) { - return new NullPointer(parent, name); - } - - JXPathEObjectInfo bi = new JXPathEObjectInfo(((EObject)bean).eClass()); - return new EObjectPointer(parent, name, bean, bi); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPropertyPointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPropertyPointer.java deleted file mode 100644 index 9ca8250d8dc..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EObjectPropertyPointer.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.List; - -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.JXPathInvalidAccessException; -import org.apache.commons.jxpath.ri.model.NodePointer; -import org.eclipse.e4.emf.internal.xpath.helper.JXPathEObjectInfo; -import org.eclipse.e4.emf.internal.xpath.helper.ValueUtils; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EStructuralFeature; - -/** - * Pointer pointing to a property of a {@link EObject}. - */ -public class EObjectPropertyPointer extends EStructuralFeaturePointer { - private static final long serialVersionUID = -6008991447676468786L; - - private static final Object UNINITIALIZED = new Object(); - - private String propertyName; - private final JXPathEObjectInfo beanInfo; - private Object baseValue = UNINITIALIZED; - private Object value = UNINITIALIZED; - private transient String[] names; - private transient EStructuralFeature[] propertyDescriptors; - private transient EStructuralFeature propertyDescriptor; - - /** - * Create a new BeanPropertyPointer. - * @param parent parent pointer - * @param beanInfo describes the target property/ies. - */ - public EObjectPropertyPointer(NodePointer parent, JXPathEObjectInfo beanInfo) { - super(parent); - this.beanInfo = beanInfo; - } - - /** - * This type of node is auxiliary. - * @return true - */ - @Override - public boolean isContainer() { - return true; - } - - @Override - public int getPropertyCount() { - if (beanInfo.isAtomic()) { - return 0; - } - return getPropertyDescriptors().length; - } - - /** - * Get the names of all properties, sorted alphabetically - * @return String[] - */ - @Override - public String[] getPropertyNames() { - if (names == null) { - EStructuralFeature[] pds = getPropertyDescriptors(); - names = new String[pds.length]; - for (int i = 0; i < names.length; i++) { - names[i] = pds[i].getName(); - } - } - return names; - } - - /** - * Select a property by name. - * @param propertyName String name - */ - @Override - public void setPropertyName(String propertyName) { - setPropertyIndex(UNSPECIFIED_PROPERTY); - this.propertyName = propertyName; - } - - /** - * Selects a property by its offset in the alphabetically sorted list. - * @param index property index - */ - @Override - public void setPropertyIndex(int index) { - if (propertyIndex != index) { - super.setPropertyIndex(index); - propertyName = null; - propertyDescriptor = null; - baseValue = UNINITIALIZED; - value = UNINITIALIZED; - } - } - - /** - * Get the value of the currently selected property. - * @return Object value - */ - @Override - public Object getBaseValue() { - if (baseValue == UNINITIALIZED) { - EStructuralFeature pd = getPropertyDescriptor(); - if (pd == null) { - return null; - } - baseValue = ValueUtils.getValue(getBean(), pd); - } - return baseValue; - } - - @Override - public void setIndex(int index) { - if (this.index == index) { - return; - } - // When dealing with a scalar, index == 0 is equivalent to - // WHOLE_COLLECTION, so do not change it. - if (this.index != WHOLE_COLLECTION - || index != 0 - || isCollection()) { - super.setIndex(index); - value = UNINITIALIZED; - } - } - - /** - * If index == WHOLE_COLLECTION, the value of the property, otherwise - * the value of the index'th element of the collection represented by the - * property. If the property is not a collection, index should be zero - * and the value will be the property itself. - * @return Object - */ - @Override - public Object getImmediateNode() { - if (value == UNINITIALIZED) { - if (index == WHOLE_COLLECTION) { - value = ValueUtils.getValue(getBaseValue()); - } - else { - EStructuralFeature pd = getPropertyDescriptor(); - if (pd == null) { - value = null; - } - else { - value = ValueUtils.getValue(getBean(), pd, index); - } - } - } - return value; - } - - @Override - protected boolean isActualProperty() { - return getPropertyDescriptor() != null; - } - - @Override - public boolean isCollection() { - EStructuralFeature pd = getPropertyDescriptor(); - - if (pd == null) { - return false; - } - - if( pd.isMany() ) { - return true; - } - -// if (pd instanceof IndexedPropertyDescriptor) { -// return true; -// } -// - int hint = ValueUtils.getCollectionHint(pd.getEType().getInstanceClass()); - if (hint == -1) { - return false; - } - if (hint == 1) { - return true; - } - - Object value = getBaseValue(); - return value != null && ValueUtils.isCollection(value); - } - - /** - * If the property contains a collection, then the length of that - * collection, otherwise - 1. - * @return int length - */ - @Override - public int getLength() { - EStructuralFeature pd = getPropertyDescriptor(); - if (pd == null) { - return 1; - } - - if( pd.isMany() ) { - return ((List)getBean().eGet(pd)).size(); - } - -// if (pd instanceof IndexedPropertyDescriptor) { -// return ValueUtils.getIndexedPropertyLength( -// getBean(), -// (IndexedPropertyDescriptor) pd); -// } -// -// int hint = ValueUtils.getCollectionHint(pd.getPropertyType()); -// if (hint == -1) { -// return 1; -// } - return ValueUtils.getLength(getBaseValue()); - } - - /** - * If index == WHOLE_COLLECTION, change the value of the property, otherwise - * change the value of the index'th element of the collection - * represented by the property. - * @param value value to set - */ - @Override - public void setValue(Object value) { - EStructuralFeature pd = getPropertyDescriptor(); - if (pd == null) { - throw new JXPathInvalidAccessException( - "Cannot set property: " + asPath() + " - no such property"); - } - - if (index == WHOLE_COLLECTION) { - ValueUtils.setValue(getBean(), pd, value); - } - else { - ValueUtils.setValue(getBean(), pd, index, value); - } - this.value = value; - } - - @Override - public NodePointer createPath(JXPathContext context) { - if (getImmediateNode() == null) { - super.createPath(context); - baseValue = UNINITIALIZED; - value = UNINITIALIZED; - } - return this; - } - - @Override - public void remove() { - if (index == WHOLE_COLLECTION) { - setValue(null); - } - else if (isCollection()) { - Object o = getBaseValue(); - Object collection = ValueUtils.remove(getBaseValue(), index); - if (collection != o) { - ValueUtils.setValue(getBean(), getPropertyDescriptor(), collection); - } - } - else if (index == 0) { - index = WHOLE_COLLECTION; - setValue(null); - } - } - - /** - * Get the name of the currently selected property. - * @return String property name - */ - @Override - public String getPropertyName() { - if (propertyName == null) { - EStructuralFeature pd = getPropertyDescriptor(); - if (pd != null) { - propertyName = pd.getName(); - } - } - return propertyName != null ? propertyName : "*"; - } - - /** - * Finds the property descriptor corresponding to the current property - * index. - * @return PropertyDescriptor - */ - private EStructuralFeature getPropertyDescriptor() { - if (propertyDescriptor == null) { - int inx = getPropertyIndex(); - if (inx == UNSPECIFIED_PROPERTY) { - propertyDescriptor = - beanInfo.getPropertyDescriptor(propertyName); - } - else { - EStructuralFeature[] propertyDescriptors = - getPropertyDescriptors(); - if (inx >= 0 && inx < propertyDescriptors.length) { - propertyDescriptor = propertyDescriptors[inx]; - } - else { - propertyDescriptor = null; - } - } - } - return propertyDescriptor; - } - - /** - * Get all PropertyDescriptors. - * @return PropertyDescriptor[] - */ - protected synchronized EStructuralFeature[] getPropertyDescriptors() { - if (propertyDescriptors == null) { - propertyDescriptors = beanInfo.getPropertyDescriptors(); - } - return propertyDescriptors; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeatureIterator.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeatureIterator.java deleted file mode 100644 index 57b1b84485a..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeatureIterator.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.JXPathException; -import org.apache.commons.jxpath.ri.model.NodeIterator; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * Iterates property values of an object pointed at with a {@link EStructuralFeatureOwnerPointer}. - * Examples of such objects are JavaBeans and objects with Dynamic Properties. - */ -public class EStructuralFeatureIterator implements NodeIterator { - private boolean empty = false; - private boolean reverse; - private String name; - private int startIndex = 0; - private boolean targetReady = false; - private int position = 0; - private EStructuralFeaturePointer propertyNodePointer; - private int startPropertyIndex; - - private boolean includeStart = false; - - /** - * Create a new PropertyIterator. - * @param pointer owning pointer - * @param name property name - * @param reverse iteration order - * @param startWith beginning pointer - */ - public EStructuralFeatureIterator( - EStructuralFeatureOwnerPointer pointer, - String name, - boolean reverse, - NodePointer startWith) { - propertyNodePointer = - (EStructuralFeaturePointer) pointer.getPropertyPointer().clone(); - this.name = name; - this.reverse = reverse; - this.includeStart = true; - if (reverse) { - this.startPropertyIndex = EStructuralFeaturePointer.UNSPECIFIED_PROPERTY; - this.startIndex = -1; - } - if (startWith != null) { - while (startWith != null - && startWith.getImmediateParentPointer() != pointer) { - startWith = startWith.getImmediateParentPointer(); - } - if (startWith == null) { - throw new JXPathException( - "PropertyIerator startWith parameter is " - + "not a child of the supplied parent"); - } - this.startPropertyIndex = - ((EStructuralFeaturePointer) startWith).getPropertyIndex(); - this.startIndex = startWith.getIndex(); - if (this.startIndex == NodePointer.WHOLE_COLLECTION) { - this.startIndex = 0; - } - this.includeStart = false; - if (reverse && startIndex == -1) { - this.includeStart = true; - } - } - } - - /** - * Get the property pointer. - * @return NodePointer - */ - protected NodePointer getPropertyPointer() { - return propertyNodePointer; - } - - /** - * Reset property iteration. - */ - public void reset() { - position = 0; - targetReady = false; - } - - @Override - public NodePointer getNodePointer() { - if (position == 0) { - if (name != null) { - if (!targetReady) { - prepareForIndividualProperty(name); - } - // If there is no such property - return null - if (empty) { - return null; - } - } - else { - if (!setPosition(1)) { - return null; - } - reset(); - } - } - try { - return propertyNodePointer.getValuePointer(); - } - catch (Throwable ex) { - // @todo: should this exception be reported in any way? - NullEStructuralFeaturePointer npp = - new NullEStructuralFeaturePointer( - propertyNodePointer.getImmediateParentPointer()); - npp.setPropertyName(propertyNodePointer.getPropertyName()); - npp.setIndex(propertyNodePointer.getIndex()); - return npp.getValuePointer(); - } - } - - @Override - public int getPosition() { - return position; - } - - @Override - public boolean setPosition(int position) { - return name == null ? setPositionAllProperties(position) : setPositionIndividualProperty(position); - } - - /** - * Set position for an individual property. - * @param position int position - * @return whether this was a valid position - */ - private boolean setPositionIndividualProperty(int position) { - this.position = position; - if (position < 1) { - return false; - } - - if (!targetReady) { - prepareForIndividualProperty(name); - } - - if (empty) { - return false; - } - - int length = getLength(); - int index; - if (!reverse) { - index = position + startIndex; - if (!includeStart) { - index++; - } - if (index > length) { - return false; - } - } - else { - int end = startIndex; - if (end == -1) { - end = length - 1; - } - index = end - position + 2; - if (!includeStart) { - index--; - } - if (index < 1) { - return false; - } - } - propertyNodePointer.setIndex(index - 1); - return true; - } - - /** - * Set position for all properties - * @param position int position - * @return whether this was a valid position - */ - private boolean setPositionAllProperties(int position) { - this.position = position; - if (position < 1) { - return false; - } - - int offset; - int count = propertyNodePointer.getPropertyCount(); - if (!reverse) { - int index = 1; - for (int i = startPropertyIndex; i < count; i++) { - propertyNodePointer.setPropertyIndex(i); - int length = getLength(); - if (i == startPropertyIndex) { - length -= startIndex; - if (!includeStart) { - length--; - } - offset = startIndex + position - index; - if (!includeStart) { - offset++; - } - } - else { - offset = position - index; - } - if (index <= position && position < index + length) { - propertyNodePointer.setIndex(offset); - return true; - } - index += length; - } - } - else { - int index = 1; - int start = startPropertyIndex; - if (start == EStructuralFeaturePointer.UNSPECIFIED_PROPERTY) { - start = count - 1; - } - for (int i = start; i >= 0; i--) { - propertyNodePointer.setPropertyIndex(i); - int length = getLength(); - if (i == startPropertyIndex) { - int end = startIndex; - if (end == -1) { - end = length - 1; - } - length = end + 1; - offset = end - position + 1; - if (!includeStart) { - offset--; - length--; - } - } - else { - offset = length - (position - index) - 1; - } - - if (index <= position && position < index + length) { - propertyNodePointer.setIndex(offset); - return true; - } - index += length; - } - } - return false; - } - - /** - * Prepare for an individual property. - * @param name property name - */ - protected void prepareForIndividualProperty(String name) { - targetReady = true; - empty = true; - - String[] names = propertyNodePointer.getPropertyNames(); - if (!reverse) { - if (startPropertyIndex == EStructuralFeaturePointer.UNSPECIFIED_PROPERTY) { - startPropertyIndex = 0; - } - if (startIndex == NodePointer.WHOLE_COLLECTION) { - startIndex = 0; - } - for (int i = startPropertyIndex; i < names.length; i++) { - if (names[i].equals(name)) { - propertyNodePointer.setPropertyIndex(i); - if (i != startPropertyIndex) { - startIndex = 0; - includeStart = true; - } - empty = false; - break; - } - } - } - else { - if (startPropertyIndex == EStructuralFeaturePointer.UNSPECIFIED_PROPERTY) { - startPropertyIndex = names.length - 1; - } - if (startIndex == NodePointer.WHOLE_COLLECTION) { - startIndex = -1; - } - for (int i = startPropertyIndex; i >= 0; i--) { - if (names[i].equals(name)) { - propertyNodePointer.setPropertyIndex(i); - if (i != startPropertyIndex) { - startIndex = -1; - includeStart = true; - } - empty = false; - break; - } - } - } - } - - /** - * Computes length for the current pointer - ignores any exceptions. - * @return length - */ - private int getLength() { - int length; - try { - length = propertyNodePointer.getLength(); // TBD: cache length - } - catch (Throwable t) { - // @todo: should this exception be reported in any way? - length = 0; - } - return length; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeatureOwnerPointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeatureOwnerPointer.java deleted file mode 100644 index f7e75d45d9c..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeatureOwnerPointer.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Locale; - -import org.apache.commons.jxpath.JXPathInvalidAccessException; -import org.apache.commons.jxpath.ri.Compiler; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.compiler.NodeNameTest; -import org.apache.commons.jxpath.ri.compiler.NodeTest; -import org.apache.commons.jxpath.ri.compiler.NodeTypeTest; -import org.apache.commons.jxpath.ri.model.NodeIterator; -import org.apache.commons.jxpath.ri.model.NodePointer; -import org.eclipse.e4.emf.internal.xpath.helper.ValueUtils; - -/** - * A pointer describing a node that has properties, each of which could be - * a collection. - */ -public abstract class EStructuralFeatureOwnerPointer extends NodePointer { - private static final long serialVersionUID = 1L; - - private static final Object UNINITIALIZED = new Object(); - - private Object value = UNINITIALIZED; - - @Override - public NodeIterator childIterator(NodeTest test, boolean reverse, - NodePointer startWith) { - if (test == null) { - return createNodeIterator(null, reverse, startWith); - } - if (test instanceof NodeNameTest) { - NodeNameTest nodeNameTest = (NodeNameTest) test; - QName testName = nodeNameTest.getNodeName(); - if (isValidProperty(testName)) { - return createNodeIterator(nodeNameTest.isWildcard() ? null - : testName.toString(), reverse, startWith); - } - return null; - } - return test instanceof NodeTypeTest && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_NODE - ? createNodeIterator(null, reverse, startWith) : null; - } - - /** - * Create a NodeIterator. - * @param property property name - * @param reverse whether to iterate in reverse - * @param startWith first pointer to return - * @return NodeIterator - */ - public NodeIterator createNodeIterator(String property, boolean reverse, - NodePointer startWith) { - return new EStructuralFeatureIterator(this, property, reverse, startWith); - } - - @Override - public NodeIterator attributeIterator(QName name) { - return new EObjectAttributeIterator(this, name); - } - - /** - * Create a new PropertyOwnerPointer. - * @param parent parent pointer - * @param locale Locale - */ - protected EStructuralFeatureOwnerPointer(NodePointer parent, Locale locale) { - super(parent, locale); - } - - /** - * Create a new PropertyOwnerPointer. - * @param parent pointer - */ - protected EStructuralFeatureOwnerPointer(NodePointer parent) { - super(parent); - } - - @Override - public void setIndex(int index) { - if (this.index != index) { - super.setIndex(index); - value = UNINITIALIZED; - } - } - - @Override - public Object getImmediateNode() { - if (value == UNINITIALIZED) { - value = index == WHOLE_COLLECTION ? ValueUtils.getValue(getBaseValue()) - : ValueUtils.getValue(getBaseValue(), index); - } - return value; - } - - @Override - public abstract QName getName(); - - /** - * Learn whether name is a valid child name for this PropertyOwnerPointer. - * @param name the QName to test - * @return true if QName is a valid property name. - * @since JXPath 1.3 - */ - public boolean isValidProperty(QName name) { - return isDefaultNamespace(name.getPrefix()); - } - - /** - * Throws an exception if you try to change the root element, otherwise - * forwards the call to the parent pointer. - * @param value to set - */ - @Override - public void setValue(Object value) { - this.value = value; - if (parent != null) { - if (parent.isContainer()) { - parent.setValue(value); - } - else { - if (index == WHOLE_COLLECTION) { - throw new UnsupportedOperationException( - "Cannot setValue of an object that is not " - + "some other object's property"); - } - throw new JXPathInvalidAccessException( - "The specified collection element does not exist: " + this); - } - } - else { - throw new UnsupportedOperationException( - "Cannot replace the root object"); - } - } - - /** - * If this is a root node pointer, throws an exception; otherwise - * forwards the call to the parent node. - */ - @Override - public void remove() { - this.value = null; - if (parent != null) { - parent.remove(); - } - else { - throw new UnsupportedOperationException( - "Cannot remove an object that is not " - + "some other object's property or a collection element"); - } - } - - /** - * Get a PropertyPointer for this PropertyOwnerPointer. - * @return PropertyPointer - */ - public abstract EStructuralFeaturePointer getPropertyPointer(); - - /** - * Learn whether dynamic property declaration is supported. - * @return true if the property owner can set a property "does not exist". - * A good example is a Map. You can always assign a value to any - * key even if it has never been "declared". - */ - public boolean isDynamicPropertyDeclarationSupported() { - return false; - } - - @Override - public int compareChildNodePointers(NodePointer pointer1, - NodePointer pointer2) { - int r = pointer1.getName().toString().compareTo(pointer2.getName().toString()); - return r == 0 ? pointer1.getIndex() - pointer2.getIndex() : r; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeaturePointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeaturePointer.java deleted file mode 100644 index 33fb024a258..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/EStructuralFeaturePointer.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Objects; - -import org.apache.commons.jxpath.AbstractFactory; -import org.apache.commons.jxpath.JXPathAbstractFactoryException; -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.JXPathIntrospector; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; -import org.eclipse.e4.emf.internal.xpath.helper.ValueUtils; -import org.eclipse.emf.ecore.EObject; - -/** - * A pointer allocated by a PropertyOwnerPointer to represent the value of - * a property of the parent object. - */ -public abstract class EStructuralFeaturePointer extends NodePointer { - private static final long serialVersionUID = 1L; - - public static final int UNSPECIFIED_PROPERTY = Integer.MIN_VALUE; - - /** property index */ - protected int propertyIndex = UNSPECIFIED_PROPERTY; - - /** owning object */ - protected Object bean; - - /** - * Takes a javabean, a descriptor of a property of that object and - * an offset within that property (starting with 0). - * @param parent parent pointer - */ - public EStructuralFeaturePointer(NodePointer parent) { - super(parent); - } - - /** - * Get the property index. - * @return int index - */ - public int getPropertyIndex() { - return propertyIndex; - } - - /** - * Set the property index. - * @param index property index - */ - public void setPropertyIndex(int index) { - if (propertyIndex != index) { - propertyIndex = index; - setIndex(WHOLE_COLLECTION); - } - } - - /** - * Get the parent bean. - * @return Object - */ - public EObject getBean() { - if (bean == null) { - bean = getImmediateParentPointer().getNode(); - } - return (EObject) bean; - } - - @Override - public QName getName() { - return new QName(null, getPropertyName()); - } - - /** - * Get the property name. - * @return String property name. - */ - public abstract String getPropertyName(); - - /** - * Set the property name. - * @param propertyName property name to set. - */ - public abstract void setPropertyName(String propertyName); - - /** - * Count the number of properties represented. - * @return int - */ - public abstract int getPropertyCount(); - - /** - * Get the names of the included properties. - * @return String[] - */ - public abstract String[] getPropertyNames(); - - /** - * Learn whether this pointer references an actual property. - * @return true if actual - */ - protected abstract boolean isActualProperty(); - - @Override - public boolean isActual() { - if (!isActualProperty()) { - return false; - } - - return super.isActual(); - } - - private static final Object UNINITIALIZED = new Object(); - - private Object value = UNINITIALIZED; - - @Override - public Object getImmediateNode() { - if (value == UNINITIALIZED) { - value = index == WHOLE_COLLECTION ? ValueUtils.getValue(getBaseValue()) - : ValueUtils.getValue(getBaseValue(), index); - } - return value; - } - - @Override - public boolean isCollection() { - Object value = getBaseValue(); - return value != null && ValueUtils.isCollection(value); - } - - @Override - public boolean isLeaf() { - Object value = getNode(); - return value == null || JXPathIntrospector.getBeanInfo(value.getClass()).isAtomic(); - } - - /** - * If the property contains a collection, then the length of that - * collection, otherwise - 1. - * @return int length - */ - @Override - public int getLength() { - return ValueUtils.getLength(getBaseValue()); - } - - /** - * Returns a NodePointer that can be used to access the currently - * selected property value. - * @return NodePointer - */ - @Override - public NodePointer getImmediateValuePointer() { - return NodePointer.newChildNodePointer( - (NodePointer) this.clone(), - getName(), - getImmediateNode()); - } - - @Override - public NodePointer createPath(JXPathContext context) { - if (getImmediateNode() == null) { - AbstractFactory factory = getAbstractFactory(context); - int inx = (index == WHOLE_COLLECTION ? 0 : index); - boolean success = - factory.createObject( - context, - this, - getBean(), - getPropertyName(), - inx); - if (!success) { - throw new JXPathAbstractFactoryException("Factory " + factory - + " could not create an object for path: " + asPath()); - } - } - return this; - } - - @Override - public NodePointer createPath(JXPathContext context, Object value) { - // If neccessary, expand collection - if (index != WHOLE_COLLECTION && index >= getLength()) { - createPath(context); - } - setValue(value); - return this; - } - - @Override - public NodePointer createChild( - JXPathContext context, - QName name, - int index, - Object value) { - EStructuralFeaturePointer prop = (EStructuralFeaturePointer) clone(); - if (name != null) { - prop.setPropertyName(name.toString()); - } - prop.setIndex(index); - return prop.createPath(context, value); - } - - @Override - public NodePointer createChild( - JXPathContext context, - QName name, - int index) { - EStructuralFeaturePointer prop = (EStructuralFeaturePointer) clone(); - if (name != null) { - prop.setPropertyName(name.toString()); - } - prop.setIndex(index); - return prop.createPath(context); - } - - @Override - public int hashCode() { - return getImmediateParentPointer().hashCode() + propertyIndex + index; - } - - @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - - if (!(object instanceof EStructuralFeaturePointer)) { - return false; - } - - EStructuralFeaturePointer other = (EStructuralFeaturePointer) object; - if (!Objects.equals(parent, other.parent)) { - return false; - } - - if (getPropertyIndex() != other.getPropertyIndex() - || !getPropertyName().equals(other.getPropertyName())) { - return false; - } - - int iThis = (index == WHOLE_COLLECTION ? 0 : index); - int iOther = (other.index == WHOLE_COLLECTION ? 0 : other.index); - return iThis == iOther; - } - - @Override - public int compareChildNodePointers( - NodePointer pointer1, - NodePointer pointer2) { - return getValuePointer().compareChildNodePointers(pointer1, pointer2); - } - -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/JXPathContextFactoryImpl.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/JXPathContextFactoryImpl.java deleted file mode 100644 index a07e323ea7c..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/JXPathContextFactoryImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2024 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.eclipse.e4.emf.xpath.XPathContext; -import org.eclipse.e4.emf.xpath.XPathContextFactory; - - -/** - * Factory creating context using JXPath - * - * @param the object the XPath is created for - */ -public class JXPathContextFactoryImpl extends XPathContextFactory { - - @Override - public XPathContext newContext(XPathContext parentContext, Object contextBean) { - return new JXPathContextImpl(parentContext, contextBean); - } - - @Override - public XPathContext newContext(T contextBean) { - return new JXPathContextImpl(contextBean); - } - -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/JXPathContextImpl.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/JXPathContextImpl.java deleted file mode 100644 index bb35950e263..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/JXPathContextImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2015 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.jxpath.ClassFunctions; -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.NodeSet; -import org.apache.commons.jxpath.Pointer; -import org.apache.commons.jxpath.util.TypeUtils; -import org.eclipse.e4.emf.xpath.XPathContext; -import org.eclipse.emf.ecore.EObject; - -/** - * Context which uses JXPath to evaluate XPath expressions - */ -public final class JXPathContextImpl implements XPathContext { - - private JXPathContext context; - - public static class EMFFunctions { - public static String eClassName(Object o) { - if( o instanceof Collection ) { - if( ! ((Collection) o).isEmpty() ) { - return eClassName(((Collection) o).iterator().next()); - } - } else if( o instanceof EObject ) { - return ((EObject) o).eClass().getName(); - } else if( o instanceof NodeSet ) { - List l = ((NodeSet) o).getValues(); - if( l.size() > 0 && l.get(0) instanceof EObject ) { - return eClassName(l.get(0)); - } - } else if( o instanceof Pointer ) { - if( ((Pointer) o).getValue() instanceof EObject ) { - return eClassName(((Pointer) o).getValue()); - } - } - - return null; - } - } - - /** - * Create a new context - * - * @param contextBean - * the context bean (=root of the xpath expression) - */ - JXPathContextImpl(Object contextBean) { - this.context = JXPathContext.newContext(contextBean); - this.context.setFunctions(new ClassFunctions(EMFFunctions.class, "ecore")); - } - - /** - * Create a new child context - * - * @param parentContext - * the parent - * @param contextBean - * the context bean (=root of the xpath expression) - */ - JXPathContextImpl(XPathContext parentContext, Object contextBean) { - JXPathContext jContext = ((JXPathContextImpl) parentContext).getJXPathContext(); - this.context = JXPathContext.newContext(jContext, contextBean); - } - - @Override - public Object getValue(String xpath) { - return context.getValue(xpath); - } - - @Override - public T getValue(String xpath, Class requiredType) { - Object value = context.getValue(xpath, requiredType); - @SuppressWarnings("unchecked") - T typedValue = (T) TypeUtils.convert(value, requiredType); - return typedValue; - } - - @Override - public Iterator iterate(String xpath) { - return context.iterate(xpath); - } - - private JXPathContext getJXPathContext() { - return context; - } - -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/LangAttributePointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/LangAttributePointer.java deleted file mode 100644 index 2f65cff0bdf..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/LangAttributePointer.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.compiler.NodeTest; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * A Pointer that points to the "lang" attribute of a JavaBean. The value - * of the attribute is based on the locale supplied to it in the constructor. - */ -public class LangAttributePointer extends NodePointer { - - private static final long serialVersionUID = -8665319197100034134L; - - /** - * Create a new LangAttributePointer. - * @param parent parent pointer. - */ - public LangAttributePointer(NodePointer parent) { - super(parent); - } - - @Override - public QName getName() { - return new QName("xml", "lang"); - } - - @Override - public String getNamespaceURI() { - return null; - } - - @Override - public boolean isCollection() { - return false; - } - - @Override - public int getLength() { - return 1; - } - - @Override - public Object getBaseValue() { - return parent.getLocale().toString().replace('_', '-'); - } - - @Override - public Object getImmediateNode() { - return getBaseValue(); - } - - @Override - public boolean isLeaf() { - return true; - } - - /** - * {@inheritDoc} - * - * Throws UnsupportedOperationException. - * @param value Object - */ - @Override - public void setValue(Object value) { - throw new UnsupportedOperationException( - "Cannot change locale using the 'lang' attribute"); - } - - @Override - public String asPath() { - StringBuilder buffer = new StringBuilder(); - if (parent != null) { - buffer.append(parent.asPath()); - if (buffer.length() == 0 - || buffer.charAt(buffer.length() - 1) != '/') { - buffer.append('/'); - } - } - buffer.append("@xml:lang"); - return buffer.toString(); - } - - @Override - public int hashCode() { - return 0; - } - - @Override - public boolean equals(Object object) { - return object instanceof LangAttributePointer; - } - - @Override - public boolean testNode(NodeTest test) { - return false; - } - - @Override - public int compareChildNodePointers( - NodePointer pointer1, - NodePointer pointer2) { - // Won't happen - lang attributes don't have children - return 0; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullEStructuralFeaturePointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullEStructuralFeaturePointer.java deleted file mode 100644 index 45a9a67bf50..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullEStructuralFeaturePointer.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.AbstractFactory; -import org.apache.commons.jxpath.JXPathAbstractFactoryException; -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.JXPathInvalidAccessException; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; - -public class NullEStructuralFeaturePointer extends EStructuralFeaturePointer { - - private String propertyName = "*"; - private boolean byNameAttribute = false; - - private static final long serialVersionUID = 5296593071854982754L; - - /** - * Create a new NullPropertyPointer. - * @param parent pointer - */ - public NullEStructuralFeaturePointer(NodePointer parent) { - super(parent); - } - - @Override - public QName getName() { - return new QName(propertyName); - } - - @Override - public void setPropertyIndex(int index) { - } - - @Override - public int getLength() { - return 0; - } - - @Override - public Object getBaseValue() { - return null; - } - - @Override - public Object getImmediateNode() { - return null; - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public NodePointer getValuePointer() { - return new NullPointer(this, new QName(getPropertyName())); - } - - @Override - protected boolean isActualProperty() { - return false; - } - - @Override - public boolean isActual() { - return false; - } - - @Override - public boolean isContainer() { - return true; - } - - @Override - public void setValue(Object value) { - if (parent == null || parent.isContainer()) { - throw new JXPathInvalidAccessException( - "Cannot set property " - + asPath() - + ", the target object is null"); - } - if (parent instanceof EStructuralFeatureOwnerPointer - && ((EStructuralFeatureOwnerPointer) parent) - .isDynamicPropertyDeclarationSupported()) { - // If the parent property owner can create - // a property automatically - let it do so - EStructuralFeaturePointer propertyPointer = - ((EStructuralFeatureOwnerPointer) parent).getPropertyPointer(); - propertyPointer.setPropertyName(propertyName); - propertyPointer.setValue(value); - } - else { - throw new JXPathInvalidAccessException( - "Cannot set property " - + asPath() - + ", path does not match a changeable location"); - } - } - - @Override - public NodePointer createPath(JXPathContext context) { - NodePointer newParent = parent.createPath(context); - if (isAttribute()) { - return newParent.createAttribute(context, getName()); - } - if (parent instanceof NullPointer && parent.equals(newParent)) { - throw createBadFactoryException(context.getFactory()); - } - // Consider these two use cases: - // 1. The parent pointer of NullPropertyPointer is - // a PropertyOwnerPointer other than NullPointer. When we call - // createPath on it, it most likely returns itself. We then - // take a PropertyPointer from it and get the PropertyPointer - // to expand the collection for the corresponding property. - // - // 2. The parent pointer of NullPropertyPointer is a NullPointer. - // When we call createPath, it may return a PropertyOwnerPointer - // or it may return anything else, like a DOMNodePointer. - // In the former case we need to do exactly what we did in use - // case 1. In the latter case, we simply request that the - // non-property pointer expand the collection by itself. - if (newParent instanceof EStructuralFeatureOwnerPointer) { - EStructuralFeatureOwnerPointer pop = (EStructuralFeatureOwnerPointer) newParent; - newParent = pop.getPropertyPointer(); - } - return newParent.createChild(context, getName(), getIndex()); - } - - @Override - public NodePointer createPath(JXPathContext context, Object value) { - NodePointer newParent = parent.createPath(context); - if (isAttribute()) { - NodePointer pointer = newParent.createAttribute(context, getName()); - pointer.setValue(value); - return pointer; - } - if (parent instanceof NullPointer && parent.equals(newParent)) { - throw createBadFactoryException(context.getFactory()); - } - if (newParent instanceof EStructuralFeatureOwnerPointer) { - EStructuralFeatureOwnerPointer pop = (EStructuralFeatureOwnerPointer) newParent; - newParent = pop.getPropertyPointer(); - } - return newParent.createChild(context, getName(), index, value); - } - - @Override - public NodePointer createChild(JXPathContext context, QName name, int index) { - return createPath(context).createChild(context, name, index); - } - - @Override - public NodePointer createChild(JXPathContext context, QName name, - int index, Object value) { - return createPath(context).createChild(context, name, index, value); - } - - @Override - public String getPropertyName() { - return propertyName; - } - - @Override - public void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - /** - * Set the name attribute. - * @param attributeValue value to set - */ - public void setNameAttributeValue(String attributeValue) { - this.propertyName = attributeValue; - byNameAttribute = true; - } - - @Override - public boolean isCollection() { - return getIndex() != WHOLE_COLLECTION; - } - - @Override - public int getPropertyCount() { - return 0; - } - - @Override - public String[] getPropertyNames() { - return new String[0]; - } - - @Override - public String asPath() { - if (!byNameAttribute) { - return super.asPath(); - } - StringBuilder buffer = new StringBuilder(); - buffer.append(getImmediateParentPointer().asPath()); - buffer.append("[@name='"); - buffer.append(escape(getPropertyName())); - buffer.append("']"); - if (index != WHOLE_COLLECTION) { - buffer.append('[').append(index + 1).append(']'); - } - return buffer.toString(); - } - - /** - * Create a "bad factory" JXPathAbstractFactoryException for the specified AbstractFactory. - * @param factory AbstractFactory - * @return JXPathAbstractFactoryException - */ - private JXPathAbstractFactoryException createBadFactoryException(AbstractFactory factory) { - return new JXPathAbstractFactoryException("Factory " + factory - + " reported success creating object for path: " + asPath() - + " but object was null. Terminating to avoid stack recursion."); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullElementPointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullElementPointer.java deleted file mode 100644 index 0442acfa234..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullElementPointer.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * Used when there is a need to construct a Pointer for a collection element - * that does not exist. For example, if the path is "foo[3]", but the - * collection "foo" only has one element or is empty or is null, the - * NullElementPointer can be used to capture this situation without putting a - * regular NodePointer into an invalid state. Just create a NullElementPointer - * with index 2 (= 3 - 1) and a "foo" pointer as the parent. - */ -public class NullElementPointer extends CollectionPointer { - - private static final long serialVersionUID = 8714236818791036721L; - - /** - * Create a new NullElementPointer. - * @param parent parent pointer - * @param index int - */ - public NullElementPointer(NodePointer parent, int index) { - super(parent, (Object) null); - this.index = index; - } - - @Override - public QName getName() { - return null; - } - - @Override - public Object getBaseValue() { - return null; - } - - @Override - public Object getImmediateNode() { - return null; - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public boolean isCollection() { - return false; - } - - /** - * Get the property pointer for this. - * @return PropertyPointer - */ - public EStructuralFeaturePointer getPropertyPointer() { - return new NullEStructuralFeaturePointer(this); - } - - @Override - public NodePointer getValuePointer() { - return new NullPointer(this, getName()); - } - - @Override - public void setValue(Object value) { - throw new UnsupportedOperationException( - "Collection element does not exist: " + this); - } - - @Override - public boolean isActual() { - return false; - } - - @Override - public boolean isContainer() { - return true; - } - - @Override - public NodePointer createPath(JXPathContext context) { - return parent.createChild(context, null, index); - } - - @Override - public NodePointer createPath(JXPathContext context, Object value) { - return parent.createChild(context, null, index, value); - } - - @Override - public int hashCode() { - return getImmediateParentPointer().hashCode() + index; - } - - @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - - if (!(object instanceof NullElementPointer)) { - return false; - } - - NullElementPointer other = (NullElementPointer) object; - return getImmediateParentPointer() == other.getImmediateParentPointer() - && index == other.index; - } - - @Override - public int getLength() { - return 0; - } - - @Override - public String asPath() { - StringBuilder buffer = new StringBuilder(); - NodePointer parent = getImmediateParentPointer(); - if (parent != null) { - buffer.append(parent.asPath()); - } - if (index != WHOLE_COLLECTION) { - // Address the list[1][2] case - if (parent != null && parent.getIndex() != WHOLE_COLLECTION) { - buffer.append("/."); - } - else if (parent != null - && parent.getImmediateParentPointer() != null - && parent.getImmediateParentPointer().getIndex() != WHOLE_COLLECTION) { - buffer.append("/."); - } - buffer.append("[").append(index + 1).append(']'); - } - - return buffer.toString(); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullPointer.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullPointer.java deleted file mode 100644 index c9493e874e5..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/NullPointer.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath; - -import java.util.Locale; -import java.util.Objects; - -import org.apache.commons.jxpath.JXPathContext; -import org.apache.commons.jxpath.ri.QName; -import org.apache.commons.jxpath.ri.model.NodePointer; - -/** - * Pointer whose value is null. - */ -public class NullPointer extends EStructuralFeatureOwnerPointer { - private QName name; - private String id; - - private static final long serialVersionUID = 2193425983220679887L; - - /** - * Create a new NullPointer. - * @param name node name - * @param locale Locale - */ - public NullPointer(QName name, Locale locale) { - super(null, locale); - this.name = name; - } - - /** - * Used for the root node. - * @param parent parent pointer - * @param name node name - */ - public NullPointer(NodePointer parent, QName name) { - super(parent); - this.name = name; - } - - /** - * Create a new NullPointer. - * @param locale Locale - * @param id String - */ - public NullPointer(Locale locale, String id) { - super(null, locale); - this.id = id; - } - - @Override - public QName getName() { - return name; - } - - @Override - public Object getBaseValue() { - return null; - } - - @Override - public boolean isCollection() { - return false; - } - - @Override - public boolean isLeaf() { - return true; - } - - @Override - public boolean isActual() { - return false; - } - - @Override - public EStructuralFeaturePointer getPropertyPointer() { - return new NullEStructuralFeaturePointer(this); - } - - @Override - public NodePointer createPath(JXPathContext context, Object value) { - if (parent != null) { - return parent.createPath(context, value).getValuePointer(); - } - throw new UnsupportedOperationException( - "Cannot create the root object: " + asPath()); - } - - @Override - public NodePointer createPath(JXPathContext context) { - if (parent != null) { - return parent.createPath(context).getValuePointer(); - } - throw new UnsupportedOperationException( - "Cannot create the root object: " + asPath()); - } - - @Override - public NodePointer createChild( - JXPathContext context, - QName name, - int index) { - return createPath(context).createChild(context, name, index); - } - - @Override - public NodePointer createChild( - JXPathContext context, - QName name, - int index, - Object value) { - return createPath(context).createChild(context, name, index, value); - } - - @Override - public int hashCode() { - return Objects.hashCode(name); - } - - @Override - public boolean equals(Object object) { - if (object == this) { - return true; - } - - if (!(object instanceof NullPointer)) { - return false; - } - - NullPointer other = (NullPointer) object; - return Objects.equals(name, other.name); - } - - @Override - public String asPath() { - if (id != null) { - return "id(" + id + ")"; - } - return parent == null ? "null()" : super.asPath(); - } - - @Override - public int getLength() { - return 0; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/EDynamicPropertyHandler.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/EDynamicPropertyHandler.java deleted file mode 100644 index d665aad20fa..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/EDynamicPropertyHandler.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 itemis AG. - * - * 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: - * Karsten Thoms - Initial implementation and API - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath.helper; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.jxpath.DynamicPropertyHandler; -import org.eclipse.core.runtime.Assert; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EStructuralFeature; - -/** - * A dynamic property handler for EMF classes. - * - * @author Karsten Thoms <karsten.thoms@itemis.de> - */ -public class EDynamicPropertyHandler implements DynamicPropertyHandler { - private Map eClass2PropNames = new HashMap<>(); - - @Override - public String[] getPropertyNames(Object object) { - Assert.isLegal(object instanceof EObject); - EClass eClass = ((EObject) object).eClass(); - return eClass2PropNames.computeIfAbsent(eClass, - clz -> clz.getEAllStructuralFeatures().stream().map(EStructuralFeature::getName).toArray(String[]::new)); - } - - @Override - public Object getProperty(Object object, String propertyName) { - Assert.isLegal(object instanceof EObject); - EObject eObject = (EObject) object; - EStructuralFeature feature = eObject.eClass().getEStructuralFeature(propertyName); - return feature != null ? eObject.eGet(feature) : null; - } - - @Override - public void setProperty(Object object, String propertyName, Object value) { - Assert.isLegal(object instanceof EObject); - EObject eObject = (EObject) object; - EStructuralFeature feature = eObject.eClass().getEStructuralFeature(propertyName); - if (feature != null) { - eObject.eSet(feature, value); - } - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/JXPathEObjectInfo.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/JXPathEObjectInfo.java deleted file mode 100644 index eaa782b5717..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/JXPathEObjectInfo.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2010, 2015 BestSolution.at and others. - * - * 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: - * Tom Schindl - initial API and implementation - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath.helper; - -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EStructuralFeature; - -public class JXPathEObjectInfo { - private final EClass eClass; - - public JXPathEObjectInfo(EClass eClass) { - this.eClass = eClass; - } - - public EStructuralFeature[] getPropertyDescriptors() { - return eClass.getEAllStructuralFeatures().toArray(new EStructuralFeature[0]); - } - - public EStructuralFeature getPropertyDescriptor(String propertyName) { - return eClass.getEStructuralFeature(propertyName); - } - - public boolean isAtomic() { - return false; - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/ValueUtils.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/ValueUtils.java deleted file mode 100644 index e37935a7004..00000000000 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/internal/xpath/helper/ValueUtils.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/******************************************************************************* - * Copyright (c) 2010 BestSolution.at and others. - * - * 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: - * Tom Schindl - adjustment to EObject - ******************************************************************************/ -package org.eclipse.e4.emf.internal.xpath.helper; - -import java.lang.reflect.Array; -import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.jxpath.Container; -import org.apache.commons.jxpath.JXPathException; -import org.apache.commons.jxpath.util.TypeUtils; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EStructuralFeature; - -/** - * Collection and property access utilities. - */ -public class ValueUtils { - - public static Object getValue(EObject bean, EStructuralFeature pd) { - return bean.eGet(pd); - } - - /** - * Returns true if the object is an array or a Collection. - * @param value to test - * @return boolean - */ - public static boolean isCollection(Object value) { - value = getValue(value); - if (value == null) { - return false; - } - if (value.getClass().isArray()) { - return true; - } - if (value instanceof Collection) { - return true; - } - return false; - } - - /** - * If the parameter is a container, opens the container and - * return the contents. The method is recursive. - * @param object to read - * @return Object - */ - public static Object getValue(Object object) { - while (object instanceof Container) { - object = ((Container) object).getValue(); - } - return object; - } - - /** - * Returns the length of the supplied collection. If the supplied object - * is not a collection, returns 1. If collection is null, returns 0. - * @param collection to check - * @return int - */ - public static int getLength(Object collection) { - if (collection == null) { - return 0; - } - collection = getValue(collection); - if (collection.getClass().isArray()) { - return Array.getLength(collection); - } - if (collection instanceof Collection) { - return ((Collection) collection).size(); - } - return 1; - } - - /** - * Remove the index'th element from the supplied collection. - * @param collection to edit - * @param index int - * @return the resulting collection - */ - public static Object remove(Object collection, int index) { - collection = getValue(collection); - if (collection == null) { - return null; - } - if (index >= getLength(collection)) { - throw new JXPathException("No such element at index " + index); - } - if (collection.getClass().isArray()) { - int length = Array.getLength(collection); - Object smaller = - Array.newInstance( - collection.getClass().getComponentType(), - length - 1); - if (index > 0) { - System.arraycopy(collection, 0, smaller, 0, index); - } - if (index < length - 1) { - System.arraycopy( - collection, - index + 1, - smaller, - index, - length - index - 1); - } - return smaller; - } - if (collection instanceof List) { - int size = ((List) collection).size(); - if (index < size) { - ((List) collection).remove(index); - } - return collection; - } - if (collection instanceof Collection) { - Iterator it = ((Collection) collection).iterator(); - for (int i = 0; i < index; i++) { - if (!it.hasNext()) { - break; - } - it.next(); - } - if (it.hasNext()) { - it.next(); - it.remove(); - } - return collection; - } - throw new JXPathException( - "Cannot remove " - + collection.getClass().getName() - + "[" - + index - + "]"); - } - - @SuppressWarnings("unchecked") - public static Object getValue(EObject bean, EStructuralFeature pd, int index) { - if (pd.isMany()) { - try { - return ((List)bean.eGet(pd)).get(index); - } - catch (IndexOutOfBoundsException ex) { - return null; - } - catch (Throwable ex) { - throw new JXPathException( - "Cannot access property: " + pd.getName(), - ex); - } - } - - // We will fall through if there is no indexed read - - return getValue(getValue(bean, pd), index); - } - - @SuppressWarnings("unchecked") - public static Object getValue(Object collection, int index) { - collection = getValue(collection); - Object value = collection; - if (collection != null) { - if (collection.getClass().isArray()) { - if (index < 0 || index >= Array.getLength(collection)) { - return null; - } - value = Array.get(collection, index); - } - else if (collection instanceof List) { - if (index < 0 || index >= ((List) collection).size()) { - return null; - } - value = ((List) collection).get(index); - } - else if (collection instanceof Collection) { - int i = 0; - Iterator it = ((Collection) collection).iterator(); - for (; i < index; i++) { - it.next(); - } - if (it.hasNext()) { - value = it.next(); - } - else { - value = null; - } - } - } - return value; - } - - public static int getCollectionHint(Class clazz) { - if (clazz.isArray()) { - return 1; - } - - if (Collection.class.isAssignableFrom(clazz)) { - return 1; - } - - if (clazz.isPrimitive()) { - return -1; - } - - if (clazz.isInterface()) { - return 0; - } - - if (Modifier.isFinal(clazz.getModifiers())) { - return -1; - } - - return 0; - } - - @SuppressWarnings("unchecked") - public static void setValue(EObject bean, EStructuralFeature pd, - Object value) { - try { - if( pd.isMany() ) { - List l = (List) bean.eGet(pd); - l.clear(); - l.addAll((Collection)value); - } else { - bean.eSet(pd, value); - } - } - catch (Exception ex) { - throw new JXPathException( - "Cannot modify property: " - + (bean == null ? "null" : bean.getClass().getName()) - + "." - + pd.getName(), - ex); - } - } - - public static void setValue(EObject bean, EStructuralFeature pd, int index, - Object value) { - if (pd.isMany()) { - try { - @SuppressWarnings("unchecked") - List l = (List) bean.eGet(pd); - l.set(index, convert(value, pd.getEType().getInstanceClass())); - } - catch (Exception ex) { - throw new RuntimeException( - "Cannot access property: " - + pd.getName() - + ", " - + ex.getMessage()); - } - } - // We will fall through if there is no indexed read - Object collection = getValue(bean, pd); - if (isCollection(collection)) { - setValue(collection, index, value); - } - else if (index == 0) { - setValue(bean, pd, value); - } - else { - throw new RuntimeException( - "Not a collection: " + pd.getName()); - } - } - - @SuppressWarnings("unchecked") - public static void setValue(Object collection, int index, Object value) { - collection = getValue(collection); - if (collection != null) { - if (collection.getClass().isArray()) { - Array.set( - collection, - index, - convert(value, collection.getClass().getComponentType())); - } - else if (collection instanceof List) { - ((List) collection).set(index, value); - } - else if (collection instanceof Collection) { - throw new UnsupportedOperationException( - "Cannot set value of an element of a " - + collection.getClass().getName()); - } - } - } - - private static Object convert(Object value, Class type) { - try { - return TypeUtils.convert(value, type); - } - catch (Exception ex) { - throw new JXPathException( - "Cannot convert value of class " - + (value == null ? "null" : value.getClass().getName()) - + " to type " - + type, - ex); - } - } - - public static Object expandCollection(Object collection, int size) { - if (collection == null) { - return null; - } - if (size < getLength(collection)) { - throw new JXPathException("adjustment of " + collection - + " to size " + size + " is not an expansion"); - } - if (collection.getClass().isArray()) { - Object bigger = - Array.newInstance( - collection.getClass().getComponentType(), - size); - System.arraycopy( - collection, - 0, - bigger, - 0, - Array.getLength(collection)); - return bigger; - } - if (collection instanceof Collection) { - @SuppressWarnings("unchecked") - Collection c = (Collection) collection; - while (c.size() < size) { - c.add(null); - } - return collection; - } - throw new JXPathException( - "Cannot turn " - + collection.getClass().getName() - + " into a collection of size " - + size); - } -} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java index 2d8c27b1224..47f9689e0de 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2015 BestSolution.at and others. + * Copyright (c) 2010, 2025 BestSolution.at and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -13,9 +13,7 @@ ******************************************************************************/ package org.eclipse.e4.emf.xpath; -import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl; -import org.eclipse.e4.emf.internal.xpath.EObjectPointerFactory; -import org.eclipse.e4.emf.internal.xpath.JXPathContextFactoryImpl; +import org.eclipse.e4.emf.xpath.internal.java.JavaXPathContextFactoryImpl; import org.eclipse.emf.ecore.EObject; /** @@ -23,11 +21,7 @@ * * @since 1.0 */ -public class EcoreXPathContextFactory{ - - static { - JXPathContextReferenceImpl.addNodePointerFactory(new EObjectPointerFactory()); - } +public class EcoreXPathContextFactory { /** * Create a new factory @@ -35,7 +29,7 @@ public class EcoreXPathContextFactory{ * @return the factory */ public static XPathContextFactory newInstance() { - return new JXPathContextFactoryImpl<>(); + return new JavaXPathContextFactoryImpl<>(); } } diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java index 41ead7162c3..fe24ab48698 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java @@ -19,8 +19,6 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; -import org.apache.commons.jxpath.util.TypeUtils; - /** * Context in which the xpath is executed * @@ -77,6 +75,6 @@ public interface XPathContext { default Stream stream(String xpath, Class type) { Iterator iterator = iterate(xpath); return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) - .filter(e -> TypeUtils.canConvert(e, type)).map(e -> TypeUtils.convert(e, type)).map(type::cast); + .filter(type::isInstance).map(type::cast); } } diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java index 5689f782614..3e5b503229a 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java @@ -13,7 +13,7 @@ ******************************************************************************/ package org.eclipse.e4.emf.xpath; -import org.eclipse.e4.emf.internal.xpath.JXPathContextFactoryImpl; +import org.eclipse.e4.emf.xpath.internal.java.JavaXPathContextFactoryImpl; /** * Factory responsible to create an XPath-Context @@ -46,6 +46,6 @@ public abstract class XPathContextFactory { * @return Create a new XPath-Factory */ public static XPathContextFactory newInstance() { - return new JXPathContextFactoryImpl<>(); + return new JavaXPathContextFactoryImpl<>(); } } diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java new file mode 100644 index 00000000000..34c8b0d0845 --- /dev/null +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2025, 2025 Hannes Wellmann and others. + * + * 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: + * Hannes Wellmann - initial API and implementation + ******************************************************************************/ + +package org.eclipse.e4.emf.xpath; + +/** + * An exception indicating that the value for a requested XPath could not be + * found. + * + * @since 0.6 + */ +public class XPathNotFoundException extends IllegalArgumentException { + private static final long serialVersionUID = -4174244860692153739L; + + public XPathNotFoundException(String message) { + super(message); + } + +} diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java new file mode 100644 index 00000000000..4dc93d5c421 --- /dev/null +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2023, 2025 Hannes Wellmann and others. + * + * 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: + * Hannes Wellmann - initial API and implementation + ******************************************************************************/ + +package org.eclipse.e4.emf.xpath.internal.java; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathFunction; +import javax.xml.xpath.XPathFunctionException; +import javax.xml.xpath.XPathNodes; + +import org.eclipse.e4.emf.xpath.XPathContext; +import org.eclipse.e4.emf.xpath.XPathContextFactory; +import org.eclipse.e4.emf.xpath.XPathNotFoundException; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.emf.ecore.xmi.impl.DefaultDOMHandlerImpl; +import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class JavaXPathContextFactoryImpl extends XPathContextFactory { + + private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance(); + + @Override + public XPathContext newContext(T contextBean) { + return newContext(null, contextBean); + } + + @Override + public XPathContext newContext(XPathContext parentContext, T contextBean) { + if (!(contextBean instanceof EObject rootObject)) { + throw new IllegalArgumentException(); + } + XPath xpath; + DOMMapping domMapping; + Element rootElement = null; + + if (parentContext != null) { + EObjectContext parent = (EObjectContext) parentContext; + xpath = parent.xpath; + rootElement = parent.domMapping.getElement(contextBean); + } else { + xpath = XPATH_FACTORY.newXPath(); + } + + if (rootElement != null) { + domMapping = ((EObjectContext) parentContext).domMapping; + } else { + DocumentBuilder documentBuilder; + try { + documentBuilder = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException(e); + } + Document document = documentBuilder.newDocument(); + + domMapping = new DOMMapping(); + rootElement = createElement(rootObject, document, domMapping); + xpath.setNamespaceContext(createNamespaceContext(rootElement)); + } + return new EObjectContext(rootElement, domMapping, xpath); + } + + private static class EObjectContext implements XPathContext { + + private final XPath xpath; + private final Element rootElement; + private final DOMMapping domMapping; + + private EObjectContext(Element rootElement, DOMMapping domMapping, XPath xpath) { + this.rootElement = rootElement; + this.domMapping = domMapping; + this.xpath = xpath; + this.xpath.setXPathFunctionResolver(this::resolveEMFFunctions); + } + + @Override + public Stream stream(String path, Class resultType) { + // See XPathResultType for generally supported result types + Class type = XPathNodes.class; + if (resultType == Boolean.class || resultType == String.class + || Number.class.isAssignableFrom(resultType)) { + type = resultType; + } + + // Fix the different root and allow .[predicate] and ..[predicate] which is + // actually not permitted in XPath-1 + String pathEnhanced = path; + if (path.equals("/")) { + pathEnhanced = "/" + rootElement.getTagName(); + } else if (path.startsWith("/") && !path.startsWith("//")) { + // The xpath '/' actually refers to the document but it's also expected to + // match the root object + pathEnhanced = "/" + rootElement.getTagName() + path; + } + pathEnhanced = pathEnhanced.replace("..[", "parent::node()[").replace(".[", "self::node()["); + Object result; + try { + result = xpath.evaluateExpression(pathEnhanced, rootElement, type); + } catch (XPathExpressionException e) { + throw new IllegalArgumentException("Illegal xpath: " + path, e); + } + if (!(result instanceof XPathNodes pathNodes)) { + return Stream.of(resultType.cast(result)); + } + return StreamSupport.stream(pathNodes.spliterator(), false).map(node -> { + if (node instanceof Element || node instanceof Document) { + return (EObject) domMapping.getValue(node); + } else if (node instanceof Attr attribute) { + return attribute.getValue(); + } + return node; + }).peek(Objects::requireNonNull).filter(resultType::isInstance).map(resultType::cast); + } + + @Override + @SuppressWarnings("unchecked") + public Iterator iterate(String xpath) { + return (Iterator) stream(xpath, Object.class).iterator(); + } + + @Override + public R getValue(String xpath, Class requiredType) { + return requiredType.cast(getValue(xpath)); + } + + @Override + public Object getValue(String xpath) { + Iterator iterator = iterate(xpath); + if (!iterator.hasNext()) { + throw new XPathNotFoundException("No value for xpath: " + xpath); + } + Object first = iterator.next(); + if (first instanceof EObject firstEObject) { + return reconstructReferenceList(firstEObject, xpath, iterator).orElse(first); + } + return first; + } + + private XPathFunction resolveEMFFunctions(QName functionName, int arity) { + if (arity == 1 && EcorePackage.eNS_URI.equals(functionName.getNamespaceURI()) + && "eClassName".equals(functionName.getLocalPart())) { + return args -> { + Node item = getSingleNodeArgument(args); + EObject eObject = (EObject) EObjectContext.this.domMapping.getValue(item); + return eObject == null ? null : eObject.eClass().getName(); + }; + } + return null; + } + + private static Node getSingleNodeArgument(List args) throws XPathFunctionException { + if (args != null && args.size() == 1) { + Object argument = args.get(0); + if (argument instanceof NodeList nodeList && nodeList.getLength() == 1) { + return nodeList.item(0); + } else if (argument instanceof Node node) { + return node; + } + } + throw new XPathFunctionException("Not a single node list: " + args); + } + } + + private static Element createElement(EObject eObject, Document document, DOMMapping domMapper) { + new XMLSaveImpl(Map.of(), new XMIHelperImpl(), "UTF-8").save(null, document, + Map.of(XMLResource.OPTION_ROOT_OBJECTS, List.of(eObject)), domMapper); + return document.getDocumentElement(); + } + + private static NamespaceContext createNamespaceContext(Element element) { + element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:ecore", EcorePackage.eNS_URI); + NamedNodeMap attributes = element.getAttributes(); + Map xmlnsPrefixMap = IntStream.range(0, attributes.getLength()).mapToObj(attributes::item) + .map(Attr.class::cast).filter(a -> "xmlns".equals(a.getPrefix())) + .collect(Collectors.toMap(Attr::getLocalName, Attr::getValue)); + Map xmlnsPrefixMapInverse = new HashMap<>(); + xmlnsPrefixMap.forEach((prefix, namespace) -> xmlnsPrefixMapInverse.put(namespace, prefix)); + + return new NamespaceContext() { + @Override + public String getNamespaceURI(String prefix) { + return xmlnsPrefixMap.get(prefix); + } + + @Override + public String getPrefix(String namespaceURI) { + return xmlnsPrefixMapInverse.get(namespaceURI); + } + + @Override + public Iterator getPrefixes(String namespaceURI) { + String prefix = getPrefix(namespaceURI); + return prefix == null ? Collections.emptyIterator() : List.of(prefix).iterator(); + } + }; + } + + private static class DOMMapping extends DefaultDOMHandlerImpl { + + public Element getElement(Object object) { + for (Map.Entry entry : nodeToObject.entrySet()) { + if (Objects.equals(entry.getValue(), object)) { + return (Element) entry.getKey(); + } + } + return null; + } + } + + private static Optional reconstructReferenceList(EObject first, String xpath, Iterator iterator) { + EReference containment = first.eContainmentFeature(); + if (containment != null && containment.isMany() && xpath.endsWith("/" + containment.getName())) { + EObject container = first.eContainer(); + List featureList = new ArrayList<>(); + featureList.add(first); + while (iterator.hasNext()) { + EObject next = (EObject) iterator.next(); + if (next.eContainer() != container || next.eContainmentFeature() != containment) { + break; + } + featureList.add(next); + } + return Optional.of(featureList); + } + return Optional.empty(); + } + +} diff --git a/tests/org.eclipse.e4.emf.xpath.test/META-INF/MANIFEST.MF b/tests/org.eclipse.e4.emf.xpath.test/META-INF/MANIFEST.MF index 933d7f6eb0b..da0b82175ff 100644 --- a/tests/org.eclipse.e4.emf.xpath.test/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.e4.emf.xpath.test/META-INF/MANIFEST.MF @@ -13,7 +13,6 @@ Import-Package: org.assertj.core.api;version="[3.27.0,4.0.0)" Require-Bundle: org.eclipse.e4.ui.model.workbench, org.eclipse.e4.emf.xpath, org.junit, - org.apache.commons.jxpath, org.eclipse.emf.ecore.xmi, org.eclipse.core.runtime, org.eclipse.emf.ecore, diff --git a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/EDynamicPropertyHandlerTest.java b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/EDynamicPropertyHandlerTest.java deleted file mode 100644 index 2586fceeb29..00000000000 --- a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/EDynamicPropertyHandlerTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 itemis AG. - * - * 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: - * Karsten Thoms - Initial implementation and API - ******************************************************************************/ -package org.eclipse.e4.emf.xpath.test; - -import static java.util.Arrays.stream; -import static java.util.stream.Collectors.joining; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.eclipse.e4.emf.internal.xpath.helper.EDynamicPropertyHandler; -import org.eclipse.e4.emf.xpath.test.model.xpathtest.Menu; -import org.eclipse.e4.emf.xpath.test.model.xpathtest.XpathtestFactory; -import org.junit.Test; - -public class EDynamicPropertyHandlerTest { - - @Test - public void test_getPropertyNames() { - EDynamicPropertyHandler propertyHandler = new EDynamicPropertyHandler(); - Menu menu = XpathtestFactory.eINSTANCE.createMenu(); - String propertyNames = stream(propertyHandler.getPropertyNames(menu)).sorted().collect(joining(",")); - assertEquals("children,id,label", propertyNames); - } - - @Test - public void test_getProperty() { - EDynamicPropertyHandler propertyHandler = new EDynamicPropertyHandler(); - Menu menu = XpathtestFactory.eINSTANCE.createMenu(); - menu.setLabel("foo"); - assertEquals("foo", propertyHandler.getProperty(menu, "label")); - } - - @Test - public void test_getProperty_When_UnknownProperty_Expect_NullResult() { - EDynamicPropertyHandler propertyHandler = new EDynamicPropertyHandler(); - Menu menu = XpathtestFactory.eINSTANCE.createMenu(); - assertNull(propertyHandler.getProperty(menu, "invalid")); - } - - @Test - public void test_setProperty() { - EDynamicPropertyHandler propertyHandler = new EDynamicPropertyHandler(); - Menu menu = XpathtestFactory.eINSTANCE.createMenu(); - propertyHandler.setProperty(menu, "label", "foo"); - assertEquals("foo", menu.getLabel()); - } -} diff --git a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java index 5f6a80cfc2f..7aeb35c49c2 100644 --- a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java +++ b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java @@ -25,10 +25,10 @@ import java.util.Iterator; import java.util.List; -import org.apache.commons.jxpath.JXPathNotFoundException; import org.eclipse.e4.emf.xpath.EcoreXPathContextFactory; import org.eclipse.e4.emf.xpath.XPathContext; import org.eclipse.e4.emf.xpath.XPathContextFactory; +import org.eclipse.e4.emf.xpath.XPathNotFoundException; import org.eclipse.e4.emf.xpath.test.model.xpathtest.ExtendedNode; import org.eclipse.e4.emf.xpath.test.model.xpathtest.Menu; import org.eclipse.e4.emf.xpath.test.model.xpathtest.Node; @@ -85,7 +85,7 @@ public void testSimpleQuery() { application = xpathContext.getValue("."); assertThat(application).isInstanceOf(Root.class); - assertThrows(JXPathNotFoundException.class, () -> xpathContext.getValue(".[@id='nixda']")); + assertThrows(XPathNotFoundException.class, () -> xpathContext.getValue(".[@id='nixda']")); assertFalse(xpathContext.iterate(".[@id='nixda']").hasNext()); application = xpathContext.getValue(".[@id='root']"); @@ -123,7 +123,7 @@ public void testMenuQuery() { List list = xpathContext.stream("//.[@id='menu.1']", Menu.class).toList(); // EMF model has a loop in it, it just goes back to the top - assertEquals(26, list.size()); + assertEquals(1, list.size()); } @Test @@ -136,5 +136,8 @@ public void testRelative() { List dotList = nestedXpathContext.stream(".", Node.class).toList(); assertEquals(1, dotList.size()); assertSame(firstElement, dotList.get(0)); + + List followingSiblingsList = nestedXpathContext.stream("following-sibling::*", Node.class).toList(); + assertEquals(eContents.subList(1, eContents.size()), followingSiblingsList); } }