diff options
author | antelder <antelder@13f79535-47bb-0310-9956-ffa450edef68> | 2010-11-30 18:46:45 +0000 |
---|---|---|
committer | antelder <antelder@13f79535-47bb-0310-9956-ffa450edef68> | 2010-11-30 18:46:45 +0000 |
commit | ae9b105c6718dcb91b415e257acc8b8c8bf0c6c7 (patch) | |
tree | 0d02a931e37abbfd87d4a69b534dd4b7715b6de4 /sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src | |
parent | 66ac4e82a503af71fb664f0b2c3d5099e4337066 (diff) |
Create branch for 2.0 beta2 release
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1040693 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
8 files changed, 531 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/ClientExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/ClientExtensionPoint.java new file mode 100644 index 0000000000..0829cfeca5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/ClientExtensionPoint.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.implementation.web.runtime; + +import org.apache.tuscany.sca.implementation.web.WebImplementation; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +public interface ClientExtensionPoint { + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, WebImplementation implementation); + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/ComponentContextProxy.java b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/ComponentContextProxy.java new file mode 100644 index 0000000000..64622ee76c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/ComponentContextProxy.java @@ -0,0 +1,85 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.implementation.web.runtime; + +import java.util.Collection; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ComponentContext; +import org.oasisopen.sca.RequestContext; +import org.oasisopen.sca.ServiceReference; + +/** + * Proxy ComponentContext wrappering a RuntimeComponent as the + * RuntimeComponent ComponentContext has not been created till later + */ +public class ComponentContextProxy implements ComponentContext { + + protected RuntimeComponent runtimeComponent; + + public ComponentContextProxy(RuntimeComponent runtimeComponent) { + this.runtimeComponent = runtimeComponent; + } + + protected ComponentContext getComponentContext() { + return runtimeComponent.getComponentContext(); + } + + public <B> ServiceReference<B> cast(B target) throws IllegalArgumentException { + return getComponentContext().cast(target); + } + + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) { + return getComponentContext().createSelfReference(businessInterface); + } + + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) { + return getComponentContext().createSelfReference(businessInterface, serviceName); + } + + public <B> B getProperty(Class<B> type, String propertyName) { + return getComponentContext().getProperty(type, propertyName); + } + + public RequestContext getRequestContext() { + return getComponentContext().getRequestContext(); + } + + public <B> B getService(Class<B> businessInterface, String referenceName) { + return getComponentContext().getService(businessInterface, referenceName); + } + + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + return getComponentContext().getServiceReference(businessInterface, referenceName); + } + + public <B> Collection<ServiceReference<B>> getServiceReferences(Class<B> businessInterface, String referenceName) { + return getComponentContext().getServiceReferences(businessInterface, referenceName); + } + + public <B> Collection<B> getServices(Class<B> businessInterface, String referenceName) { + return getComponentContext().getServices(businessInterface, referenceName); + } + + public String getURI() { + return getComponentContext().getURI(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/WebImplementationProviderFactory.java b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/WebImplementationProviderFactory.java new file mode 100644 index 0000000000..d0323545ea --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/WebImplementationProviderFactory.java @@ -0,0 +1,71 @@ +/* + * 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. + */ +package org.apache.tuscany.sca.implementation.web.runtime; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.host.http.ServletHostHelper; +import org.apache.tuscany.sca.implementation.web.WebImplementation; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +public class WebImplementationProviderFactory implements ImplementationProviderFactory<WebImplementation> { + + private ServletHost servletHost; + private ClientExtensionPoint jsClient; + + public WebImplementationProviderFactory(ExtensionPointRegistry extensionPoints) { + this.servletHost = ServletHostHelper.getServletHost(extensionPoints); + jsClient = extensionPoints.getExtensionPoint(ClientExtensionPoint.class); + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, WebImplementation implementation) { + servletHost.setAttribute("org.apache.tuscany.sca.implementation.web.RuntimeComponent", component); + servletHost.setAttribute("org.oasisopen.sca.ComponentContext", new ComponentContextProxy(component)); + + ImplementationProvider impl; + if (jsClient != null && implementation.getJSClient()) { + impl = jsClient.createImplementationProvider(component, implementation); + } else { + impl = new ImplementationProvider() { + + public Invoker createInvoker(RuntimeComponentService arg0, Operation arg1) { + throw new UnsupportedOperationException("Components using implementation.web have no services"); + } + public void start() { + } + public void stop() { + } + public boolean supportsOneWayInvocation() { + return false; + } + }; + } + return impl; + } + + public Class<WebImplementation> getModelType() { + return WebImplementation.class; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/jsp/ReferenceTEI.java b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/jsp/ReferenceTEI.java new file mode 100644 index 0000000000..2ba7944326 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/jsp/ReferenceTEI.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.implementation.web.runtime.jsp; + +import javax.servlet.jsp.tagext.TagData; +import javax.servlet.jsp.tagext.TagExtraInfo; +import javax.servlet.jsp.tagext.VariableInfo; + +/** + * TagExtraInfo class for the SCA reference tags + * <sca:reference name="service" type="test.MyService" scope="1" /> + * + * @version $Rev$ $Date$ + */ +public class ReferenceTEI extends TagExtraInfo { + + @Override + public VariableInfo[] getVariableInfo(TagData data) { + VariableInfo info1 + = new VariableInfo( + data.getAttributeString("name"), + data.getAttributeString("type"), + true, + VariableInfo.AT_END); + VariableInfo[] info = { info1 } ; + return info; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/jsp/ReferenceTag.java b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/jsp/ReferenceTag.java new file mode 100644 index 0000000000..b4655e3d95 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/jsp/ReferenceTag.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.implementation.web.runtime.jsp; + +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.PageContext; +import javax.servlet.jsp.tagext.TagSupport; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ServiceReference; + +/** + * Tag to handle SCA references + * <sca:reference name="service" type="test.MyService" scope="1" /> + * + * @version $Rev$ $Date$ + */ +public class ReferenceTag extends TagSupport { + private static final long serialVersionUID = 1L; + + protected String name; + protected String type; + protected Integer scope = PageContext.PAGE_SCOPE; + + @Override + public int doStartTag() throws JspException { + return SKIP_BODY; + } + + @Override + public int doEndTag() throws JspException { + + ServletContext servletContext = pageContext.getServletContext(); + RuntimeComponent component = (RuntimeComponent)servletContext.getAttribute("org.apache.tuscany.sca.implementation.web.RuntimeComponent"); + if (component == null) { + throw new JspException("No Web component found. Is there an <implementation.web> missing?"); + } + + Class<?> typeClass; + try { + typeClass = Class.forName(type, true, Thread.currentThread().getContextClassLoader()); + } catch (ClassNotFoundException e) { + throw new JspException("Reference '" + name + "' type class not found: " + type); + } + + ServiceReference<?> sr = component.getComponentContext().getServiceReference(typeClass, name); + if (sr == null) { + throw new JspException("Reference '" + name + "' undefined"); + } + + pageContext.setAttribute(name, sr.getService(), scope); + + return EVAL_PAGE; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getScope() { + return scope; + } + + public void setScope(Integer scope) { + this.scope = scope; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/utils/ContextHelper.java b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/utils/ContextHelper.java new file mode 100644 index 0000000000..423e906d6b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/java/org/apache/tuscany/sca/implementation/web/runtime/utils/ContextHelper.java @@ -0,0 +1,133 @@ +/* + * 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. + */ + +package org.apache.tuscany.sca.implementation.web.runtime.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.servlet.ServletContext; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ComponentContext; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; +import org.oasisopen.sca.annotation.ComponentName; +import org.oasisopen.sca.annotation.Context; +import org.oasisopen.sca.annotation.Property; +import org.oasisopen.sca.annotation.Reference; + +public class ContextHelper { + + public static final String COMPONENT_ATTR = "org.apache.tuscany.sca.implementation.web.RuntimeComponent"; + + public static ComponentContext getComponentContext(ServletContext sc) { + RuntimeComponent rc = (RuntimeComponent)sc.getAttribute(COMPONENT_ATTR); + return rc.getComponentContext(); + } + + public static <T> T getReference(String name, Class<T> type, ServletContext sc) { + ServiceReference<T> sr = getComponentContext(sc).getServiceReference(type, name); + if (sr == null) { + throw new ServiceRuntimeException("Reference '" + name + "' undefined"); + } + return sr.getService(); + } + + public static Object getProperty(String name, ServletContext sc) { + RuntimeComponent rc = (RuntimeComponent)sc.getAttribute(COMPONENT_ATTR); + for (ComponentProperty p : rc.getProperties()) { + if (name.equals(p.getName())) { + return p.getValue(); + } + } + return null; + } + + public static void inject(Object instance, ServletContext sc) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + + Class<?> clazz = instance.getClass(); + for (Field field : clazz.getDeclaredFields()) { + if (field.isAnnotationPresent(Reference.class)) { + Reference ref = field.getAnnotation(Reference.class); + String name = ref.name() != null && !ref.name().equals("") ? ref.name() : field.getName(); + Object value = getReference(name, field.getType(), sc); + setField(instance, field, value); + } else if (field.isAnnotationPresent(Property.class)) { + Property prop = field.getAnnotation(Property.class); + String name = prop.name() != null && !prop.name().equals("") ? prop.name() : field.getName(); + Object value = getProperty(name, sc); + setField(instance, field, value); + } else if (field.isAnnotationPresent(ComponentName.class)) { + RuntimeComponent rc = (RuntimeComponent)sc.getAttribute(COMPONENT_ATTR); + setField(instance, field, rc.getName()); + } else if (field.isAnnotationPresent(Context.class)) { + setField(instance, field, getComponentContext(sc)); + } + } + + for (Method method : clazz.getDeclaredMethods()) { + if (!method.getName().startsWith("set") || method.getParameterTypes().length != 1) { + continue; + } + String targetName = method.getName().substring(3); + Class<?> type = method.getParameterTypes()[0]; + + if (method.isAnnotationPresent(Reference.class)) { + Reference ref = method.getAnnotation(Reference.class); + String name = ref.name() != null && !ref.name().equals("") ? ref.name() : targetName; + Object value = getReference(name, type, sc); + setMethod(instance, method, value); + } else if (method.isAnnotationPresent(Property.class)) { + Property prop = method.getAnnotation(Property.class); + String name = prop.name() != null && !prop.name().equals("") ? prop.name() : targetName; + Object value = getProperty(name, sc); + setMethod(instance, method, value); + } else if (method.isAnnotationPresent(ComponentName.class)) { + RuntimeComponent rc = (RuntimeComponent)sc.getAttribute(COMPONENT_ATTR); + setMethod(instance, method, rc.getName()); + } else if (method.isAnnotationPresent(Context.class)) { + setMethod(instance, method, getComponentContext(sc)); + } + } + } + + private static void setMethod(Object instance, Method method, Object value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + if (method.isAccessible()) { + method.invoke(instance, new Object[] {value}); + } else { + method.setAccessible(true); + method.invoke(instance, new Object[] {value}); + method.setAccessible(false); + } + } + + private static void setField(Object instance, Field field, Object value) throws IllegalArgumentException, IllegalAccessException { + if (field.isAccessible()) { + field.set(instance, value); + } else { + field.setAccessible(true); + field.set(instance, value); + field.setAccessible(false); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/resources/META-INF/sca.tld b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/resources/META-INF/sca.tld new file mode 100644 index 0000000000..8a9ce93204 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/resources/META-INF/sca.tld @@ -0,0 +1,49 @@ +<?xml version = '1.0' encoding = 'ISO-8859-1'?>
+<!--
+(c) Copyright BEA Systems, Inc., Cape Clear Software, International Business Machines Corp, Interface21, IONA
+Technologies, Oracle, Primeton Technologies, Progress Software, Red Hat, Rogue Wave Software, SAP AG., Siemens
+AG., Software AG., Sun Microsystems, Inc., Sybase Inc., TIBCO Software Inc., 2005, 2008. All rights reserved.
+
+see http://www.osoa.org/display/Main/Service+Component+Architecture+Specifications
+ -->
+
+<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
+
+ <tlib-version>1.0</tlib-version>
+ <short-name>SCA-JSP</short-name>
+ <uri>http://www.osoa.org/sca/sca_jsp.tld</uri>
+ <description>A tag library for integrating sca components with jsp</description>
+
+ <tag>
+
+ <name>reference</name>
+
+ <tag-class>org.apache.tuscany.sca.implementation.web.runtime.jsp.ReferenceTag</tag-class>
+ <tei-class>org.apache.tuscany.sca.implementation.web.runtime.jsp.ReferenceTEI</tei-class>
+
+ <attribute>
+ <name>name</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+
+ <attribute>
+ <name>type</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+
+ <attribute>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ <type>java.lang.Integer</type>
+ </attribute>
+
+ <body-content>empty</body-content>
+
+ </tag>
+
+</taglib>
diff --git a/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory new file mode 100644 index 0000000000..4e26825cfe --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta2/modules/implementation-web-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory @@ -0,0 +1,21 @@ +# 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.
+
+# Implementation class for the implementation extension
+org.apache.tuscany.sca.implementation.web.runtime.WebImplementationProviderFactory;model=org.apache.tuscany.sca.implementation.web.WebImplementation;ranking=9876
+
+
|