You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2012/12/05 00:41:09 UTC
[16/52] [partial] ISIS-188: consolidating isis-core
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/ContentWriter.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/ContentWriter.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/ContentWriter.java
new file mode 100644
index 0000000..3a452d2
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/ContentWriter.java
@@ -0,0 +1,29 @@
+/*
+ * 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.isis.core.commons.xml;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public interface ContentWriter {
+
+ void write(Writer writer) throws IOException;
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/XmlFile.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/XmlFile.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/XmlFile.java
new file mode 100644
index 0000000..30d6379
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/XmlFile.java
@@ -0,0 +1,170 @@
+/*
+ * 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.isis.core.commons.xml;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.lang.ToString;
+
+public class XmlFile {
+ private static final String[] ESCAPE_STRING = { "&", "<", ">", """, "'" };
+ private static final String[] SPECIAL_CHARACTERS = { "&", "<", ">", "\"", "'" };
+
+ public static String getValueWithSpecialsEscaped(final String s) {
+ String result = s;
+ for (int i = 0; i < SPECIAL_CHARACTERS.length; i++) {
+ final String special = SPECIAL_CHARACTERS[i];
+ int pos = -1;
+ while (true) {
+ pos = result.indexOf(special, pos + 1);
+ if (pos < 0) {
+ break;
+ }
+ result = result.substring(0, pos) + ESCAPE_STRING[i] + result.substring(pos + special.length());
+ }
+ }
+ return result;
+ }
+
+ private final String charset;
+ private final File directory;
+
+ public XmlFile(final String charset, final String directory) {
+ this.directory = new File(directory);
+ createDirectoryIfRequired();
+ this.charset = charset;
+ }
+
+ private void createDirectoryIfRequired() {
+ if (this.directory.exists()) {
+ return;
+ }
+ this.directory.mkdirs();
+ }
+
+ private void createDirectoryIfRequired(File file) {
+ if(file.exists()) {
+ return;
+ }
+ file.getParentFile().mkdirs();
+ }
+
+ public File getDirectory() {
+ return directory;
+ }
+
+ private File file(final String fileName) {
+ return new File(directory, fileName + ".xml");
+ }
+
+ public void writeXml(final String name, final ContentWriter writer) {
+ OutputStreamWriter pw;
+
+ try {
+ final File file = file(name);
+ createDirectoryIfRequired(file);
+ pw = new OutputStreamWriter(new FileOutputStream(file), charset);
+ pw.write("<?xml version=\"1.0\" encoding=\"" + charset + "\" ?>\n");
+ pw.write("\n");
+ writer.write(pw);
+ pw.write("\n");
+ pw.close();
+ } catch (final IOException e) {
+ throw new IsisException("Problems writing data files", e);
+ }
+ }
+
+
+ public boolean parse(final ContentHandler handler, final String fileName) {
+ XMLReader parser;
+
+ try {
+ parser = XMLReaderFactory.createXMLReader();
+ } catch (final SAXException e) {
+ try {
+ parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
+ } catch (final SAXException e2) {
+ try {
+ parser = XMLReaderFactory.createXMLReader("org.apache.crimson.parser.XMLReaderImpl");
+ } catch (final SAXException failed) {
+ throw new IsisException("Couldn't locate a SAX parser");
+ }
+ }
+ }
+
+ final File file = file(fileName);
+ try {
+ parser.setContentHandler(handler);
+ final FileInputStream fis = new FileInputStream(file);
+ final InputStreamReader isr = new InputStreamReader(fis, charset);
+ final InputSource is = new InputSource(isr);
+ parser.parse(is);
+
+ return true;
+ } catch (final FileNotFoundException e) {
+ return false;
+ } catch (final IOException e) {
+ throw new IsisException("Error reading XML file", e);
+ } catch (final SAXParseException e) {
+ throw new IsisException("Error while parsing: " + e.getMessage() + " in " + file + ")", e);
+ } catch (final SAXException e) {
+ throw new IsisException("Error in file " + file + " ", e);
+ }
+ }
+
+ public void delete(final String fileName) {
+ file(fileName).delete();
+ }
+
+ /**
+ * The XML store is deemed to be initialised if the directory used to store
+ * the data has no xml files in it.
+ */
+ public boolean isFixturesInstalled() {
+ final String[] list = directory.list(new FilenameFilter() {
+ @Override
+ public boolean accept(final File dir, final String name) {
+ return name.toLowerCase().endsWith(".xml");
+ }
+ });
+ return list.length > 0;
+ }
+
+ @Override
+ public String toString() {
+ return new ToString(this).append("directory", this.directory).toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/package-info.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/package-info.java
new file mode 100644
index 0000000..9ec3da4
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/xml/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ * Provides helper classes for writing alternative implementations
+ * that just persist to a proprietary XML format.
+ *
+ * <p>
+ * Specifically, these classes are used by the <i>XmlObjectStore</i>
+ * and the <i>XmlProfileStore</i>.
+ */
+package org.apache.isis.core.commons.xml;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
new file mode 100644
index 0000000..2ccaa4c
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
@@ -0,0 +1,393 @@
+/*
+ * 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.isis.core.progmodel.app;
+
+import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
+import static org.apache.isis.core.commons.ensure.Ensure.ensureThatState;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.config.IsisConfigurationDefault;
+import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator;
+import org.apache.isis.core.metamodel.layout.MemberLayoutArranger;
+import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
+import org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.specloader.ObjectReflectorDefault;
+import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
+import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutorAbstract;
+import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
+import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistryDefault;
+import org.apache.isis.core.metamodel.specloader.traverser.SpecificationTraverser;
+import org.apache.isis.core.metamodel.specloader.traverser.SpecificationTraverserDefault;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+import org.apache.isis.core.progmodel.layout.dflt.MemberLayoutArrangerDefault;
+import org.apache.isis.core.progmodel.metamodelvalidator.dflt.MetaModelValidatorDefault;
+
+/**
+ * Facade for the entire Isis metamodel and supporting components.
+ *
+ * <p>
+ * Currently this is <i>not</i> used by Isis proper, but is available for use by integration tests.
+ * The intention is to factor it into <tt>IsisSystem</tt>.
+ */
+public class IsisMetaModel implements ApplicationScopedComponent {
+
+ private static enum State {
+ NOT_INITIALIZED, INITIALIZED, SHUTDOWN;
+ }
+
+ private final List<Object> services = Lists.newArrayList();
+
+ private State state = State.NOT_INITIALIZED;
+
+ private ObjectReflectorDefault reflector;
+ private RuntimeContext runtimeContext;
+
+ private IsisConfiguration configuration;
+ private ClassSubstitutor classSubstitutor;
+ private CollectionTypeRegistry collectionTypeRegistry;
+ private ProgrammingModel programmingModel;
+ private SpecificationTraverser specificationTraverser;
+ private MemberLayoutArranger memberLayoutArranger;
+ private Set<FacetDecorator> facetDecorators;
+ private MetaModelValidator metaModelValidator;
+
+ private DomainObjectContainer container;
+
+ private ValidationFailures validationFailures;
+
+
+ public static class Builder {
+ private final RuntimeContext runtimeContext;
+ private final ProgrammingModel programmingModel;
+ private DomainObjectContainer container = new DomainObjectContainerDefault();
+ private List<Object> services = Lists.newArrayList();
+
+ private Builder(RuntimeContext embeddedContext, ProgrammingModel programmingModel) {
+ this.runtimeContext = embeddedContext;
+ this.programmingModel = programmingModel;
+ }
+
+ public Builder with(DomainObjectContainer container) {
+ this.container = container;
+ return this;
+ }
+
+ public Builder withServices(Object... services) {
+ return withServices(Arrays.asList(services));
+ }
+
+ public Builder withServices(List<Object> services) {
+ this.services = services;
+ return this;
+ }
+
+ public IsisMetaModel build() {
+ final IsisMetaModel isisMetaModel = new IsisMetaModel(runtimeContext, programmingModel, services);
+ if(container != null) {
+ isisMetaModel.setContainer(container);
+ }
+ return isisMetaModel;
+ }
+ }
+
+ public static Builder builder(RuntimeContext runtimeContext, ProgrammingModel programmingModel) {
+ return new Builder(runtimeContext, programmingModel);
+ }
+
+ public IsisMetaModel(final RuntimeContext runtimeContext, ProgrammingModel programmingModel, final List<Object> services) {
+ this(runtimeContext, programmingModel, services.toArray());
+ }
+
+ public IsisMetaModel(final RuntimeContext runtimeContext, ProgrammingModel programmingModel, final Object... services) {
+ this.runtimeContext = runtimeContext;
+
+ setContainer(new DomainObjectContainerDefault());
+ this.services.addAll(Arrays.asList(services));
+ setConfiguration(new IsisConfigurationDefault());
+ setClassSubstitutor(new ClassSubstitutorAbstract() {});
+ setCollectionTypeRegistry(new CollectionTypeRegistryDefault());
+ setSpecificationTraverser(new SpecificationTraverserDefault());
+ setMemberLayoutArranger(new MemberLayoutArrangerDefault());
+ setFacetDecorators(new TreeSet<FacetDecorator>());
+ setProgrammingModelFacets(programmingModel);
+
+ setMetaModelValidator(new MetaModelValidatorDefault());
+ }
+
+ private void setContainer(DomainObjectContainer container) {
+ this.container = container;
+ }
+
+ /**
+ * The list of classes representing services, as specified in the
+ * {@link #IsisMetaModel(EmbeddedContext, Class...) constructor}.
+ *
+ * <p>
+ * To obtain the instantiated services, use the
+ * {@link ServicesInjectorSpi#getRegisteredServices()} (available from
+ * {@link #getServicesInjector()}).
+ */
+ public List<Object> getServices() {
+ return Collections.unmodifiableList(services);
+ }
+
+ // ///////////////////////////////////////////////////////
+ // init, shutdown
+ // ///////////////////////////////////////////////////////
+
+ @Override
+ public void init() {
+ ensureNotInitialized();
+ reflector = new ObjectReflectorDefault(configuration, classSubstitutor, collectionTypeRegistry, specificationTraverser, memberLayoutArranger, programmingModel, facetDecorators, metaModelValidator);
+
+ runtimeContext.injectInto(container);
+ runtimeContext.setContainer(container);
+ runtimeContext.injectInto(reflector);
+ reflector.injectInto(runtimeContext);
+
+ validationFailures = reflector.initAndValidate();
+ runtimeContext.init();
+
+ for (final Object service : services) {
+ final ObjectSpecification serviceSpec = reflector.loadSpecification(service.getClass());
+ serviceSpec.markAsService();
+ }
+ state = State.INITIALIZED;
+ }
+
+ public ValidationFailures getValidationFailures() {
+ return validationFailures;
+ }
+
+ @Override
+ public void shutdown() {
+ ensureInitialized();
+ state = State.SHUTDOWN;
+ }
+
+ // ///////////////////////////////////////////////////////
+ // SpecificationLoader
+ // ///////////////////////////////////////////////////////
+
+ /**
+ * Available once {@link #init() initialized}.
+ */
+ public SpecificationLoaderSpi getSpecificationLoader() {
+ return reflector;
+ }
+
+ // ///////////////////////////////////////////////////////
+ // DomainObjectContainer
+ // ///////////////////////////////////////////////////////
+
+ /**
+ * Available once {@link #init() initialized}.
+ */
+ public DomainObjectContainer getDomainObjectContainer() {
+ ensureInitialized();
+ return container;
+ }
+
+ // ///////////////////////////////////////////////////////
+ // DependencyInjector
+ // ///////////////////////////////////////////////////////
+
+ /**
+ * Available once {@link #init() initialized}.
+ */
+ public ServicesInjector getDependencyInjector() {
+ ensureInitialized();
+ return runtimeContext.getDependencyInjector();
+ }
+
+ // ///////////////////////////////////////////////////////
+ // Override defaults
+ // ///////////////////////////////////////////////////////
+
+ /**
+ * The {@link IsisConfiguration} in force, either defaulted or specified
+ * {@link #setConfiguration(IsisConfiguration) explicitly.}
+ */
+ public IsisConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Optionally specify the {@link IsisConfiguration}.
+ *
+ * <p>
+ * Call prior to {@link #init()}.
+ */
+ public void setConfiguration(final IsisConfiguration configuration) {
+ ensureNotInitialized();
+ ensureThatArg(configuration, is(notNullValue()));
+ this.configuration = configuration;
+ }
+
+ /**
+ * The {@link ClassSubstitutor} in force, either defaulted or specified
+ * {@link #setClassSubstitutor(ClassSubstitutor) explicitly}.
+ */
+ public ClassSubstitutor getClassSubstitutor() {
+ return classSubstitutor;
+ }
+
+ /**
+ * Optionally specify the {@link ClassSubstitutor}.
+ *
+ * <p>
+ * Call prior to {@link #init()}.
+ */
+ public void setClassSubstitutor(final ClassSubstitutor classSubstitutor) {
+ ensureNotInitialized();
+ ensureThatArg(classSubstitutor, is(notNullValue()));
+ this.classSubstitutor = classSubstitutor;
+ }
+
+ /**
+ * The {@link CollectionTypeRegistry} in force, either defaulted or
+ * specified {@link #setCollectionTypeRegistry(CollectionTypeRegistry)
+ * explicitly.}
+ */
+ public CollectionTypeRegistry getCollectionTypeRegistry() {
+ return collectionTypeRegistry;
+ }
+
+ /**
+ * Optionally specify the {@link CollectionTypeRegistry}.
+ *
+ * <p>
+ * Call prior to {@link #init()}.
+ */
+ public void setCollectionTypeRegistry(final CollectionTypeRegistry collectionTypeRegistry) {
+ ensureNotInitialized();
+ ensureThatArg(collectionTypeRegistry, is(notNullValue()));
+ this.collectionTypeRegistry = collectionTypeRegistry;
+ }
+
+ /**
+ * The {@link SpecificationTraverser} in force, either defaulted or
+ * specified {@link #setSpecificationTraverser(SpecificationTraverser)
+ * explicitly}.
+ */
+ public SpecificationTraverser getSpecificationTraverser() {
+ return specificationTraverser;
+ }
+
+ /**
+ * Optionally specify the {@link SpecificationTraverser}.
+ */
+ public void setSpecificationTraverser(final SpecificationTraverser specificationTraverser) {
+ this.specificationTraverser = specificationTraverser;
+ }
+
+ /**
+ * Optionally specify the {@link MemberLayoutArranger}.
+ */
+ public void setMemberLayoutArranger(final MemberLayoutArranger memberLayoutArranger) {
+ this.memberLayoutArranger = memberLayoutArranger;
+ }
+
+ /**
+ * The {@link ProgrammingModel} in force, either defaulted or specified
+ * {@link #setProgrammingModelFacets(ProgrammingModel) explicitly}.
+ */
+ public ProgrammingModel getProgrammingModelFacets() {
+ return programmingModel;
+ }
+
+ /**
+ * Optionally specify the {@link ProgrammingModel}.
+ *
+ * <p>
+ * Call prior to {@link #init()}.
+ */
+ public void setProgrammingModelFacets(final ProgrammingModel programmingModel) {
+ ensureNotInitialized();
+ ensureThatArg(programmingModel, is(notNullValue()));
+ this.programmingModel = programmingModel;
+ }
+
+ /**
+ * The {@link FacetDecorator}s in force, either defaulted or specified
+ * {@link #setFacetDecorators(Set) explicitly}.
+ */
+ public Set<FacetDecorator> getFacetDecorators() {
+ return Collections.unmodifiableSet(facetDecorators);
+ }
+
+ /**
+ * Optionally specify the {@link FacetDecorator}s.
+ *
+ * <p>
+ * Call prior to {@link #init()}.
+ */
+ public void setFacetDecorators(final Set<FacetDecorator> facetDecorators) {
+ ensureNotInitialized();
+ ensureThatArg(facetDecorators, is(notNullValue()));
+ this.facetDecorators = facetDecorators;
+ }
+
+ /**
+ * The {@link MetaModelValidator} in force, either defaulted or specified
+ * {@link #setMetaModelValidator(MetaModelValidator) explicitly}.
+ */
+ public MetaModelValidator getMetaModelValidator() {
+ return metaModelValidator;
+ }
+
+ /**
+ * Optionally specify the {@link MetaModelValidator}.
+ */
+ public void setMetaModelValidator(final MetaModelValidator metaModelValidator) {
+ this.metaModelValidator = metaModelValidator;
+ }
+
+ // ///////////////////////////////////////////////////////
+ // State management
+ // ///////////////////////////////////////////////////////
+
+ private State ensureNotInitialized() {
+ return ensureThatState(state, is(State.NOT_INITIALIZED));
+ }
+
+ private State ensureInitialized() {
+ return ensureThatState(state, is(State.INITIALIZED));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecorator.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecorator.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecorator.java
new file mode 100644
index 0000000..272242d
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecorator.java
@@ -0,0 +1,26 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help;
+
+import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator;
+
+public interface HelpFacetDecorator extends FacetDecorator {
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecoratorUsingHelpManager.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecoratorUsingHelpManager.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecoratorUsingHelpManager.java
new file mode 100644
index 0000000..a799ecb
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetDecoratorUsingHelpManager.java
@@ -0,0 +1,67 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.metamodel.facetdecorator.FacetDecoratorAbstract;
+import org.apache.isis.core.metamodel.facets.help.HelpFacet;
+
+public class HelpFacetDecoratorUsingHelpManager extends FacetDecoratorAbstract implements HelpFacetDecorator {
+ private final HelpManager helpManager;
+
+ public HelpFacetDecoratorUsingHelpManager(final HelpManager manager) {
+ helpManager = manager;
+ }
+
+ @Override
+ public Facet decorate(final Facet facet, final FacetHolder facetHolder) {
+ if (facet.facetType() != HelpFacet.class) {
+ return facet;
+ }
+
+ if (!(facetHolder instanceof IdentifiedHolder)) {
+ return null;
+ }
+
+ final IdentifiedHolder identifiedHolder = (IdentifiedHolder) facetHolder;
+ return decorateWithHelpFacet(facet, identifiedHolder);
+ }
+
+ private Facet decorateWithHelpFacet(final Facet facet, final IdentifiedHolder identifiedHolder) {
+ final Identifier identifier = identifiedHolder.getIdentifier();
+
+ final String helpText = helpManager.getHelpText(identifier);
+ if (helpText != null) {
+ final HelpFacetLookedUpViaHelpManager decoratingFacet = new HelpFacetLookedUpViaHelpManager(helpText, facet.getFacetHolder());
+ identifiedHolder.addFacet(decoratingFacet);
+ return decoratingFacet;
+ }
+ return null;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class<? extends Facet>[] getFacetTypes() {
+ return new Class[] { HelpFacet.class };
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetLookedUpViaHelpManager.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetLookedUpViaHelpManager.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetLookedUpViaHelpManager.java
new file mode 100644
index 0000000..8d6127b
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpFacetLookedUpViaHelpManager.java
@@ -0,0 +1,34 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.help.HelpFacetAbstract;
+
+/**
+ * Looked up via the {@link HelpManager}.
+ */
+public class HelpFacetLookedUpViaHelpManager extends HelpFacetAbstract {
+
+ public HelpFacetLookedUpViaHelpManager(final String value, final FacetHolder holder) {
+ super(value, holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManager.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManager.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManager.java
new file mode 100644
index 0000000..78d699e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManager.java
@@ -0,0 +1,34 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+
+public interface HelpManager extends ApplicationScopedComponent {
+
+ /**
+ * Returns help text for the specified {@link Identifier}.
+ *
+ * <p>
+ * If no help text is available then an empty String should be returned.
+ */
+ String getHelpText(Identifier identifier);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManagerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManagerAbstract.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManagerAbstract.java
new file mode 100644
index 0000000..8c19fd4
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/HelpManagerAbstract.java
@@ -0,0 +1,47 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help;
+
+import org.apache.isis.applib.Identifier;
+
+/**
+ * Default implementation that does nothing.
+ *
+ */
+public abstract class HelpManagerAbstract implements HelpManager {
+
+ /**
+ * Does nothing.
+ */
+ @Override
+ public void init() {
+ }
+
+ /**
+ * Does nothing.
+ */
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public abstract String getHelpText(final Identifier identifier);
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/HelpFacetDecoratorUsingFilesInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/HelpFacetDecoratorUsingFilesInstaller.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/HelpFacetDecoratorUsingFilesInstaller.java
new file mode 100644
index 0000000..1b300ea
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/HelpFacetDecoratorUsingFilesInstaller.java
@@ -0,0 +1,47 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help.file;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.isis.core.commons.config.InstallerAbstract;
+import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator;
+import org.apache.isis.core.metamodel.specloader.FacetDecoratorInstaller;
+import org.apache.isis.core.progmodel.facetdecorators.help.HelpFacetDecoratorUsingHelpManager;
+import org.apache.isis.core.progmodel.facetdecorators.help.file.internal.HelpManagerUsingFiles;
+
+public class HelpFacetDecoratorUsingFilesInstaller extends InstallerAbstract implements FacetDecoratorInstaller {
+
+ public HelpFacetDecoratorUsingFilesInstaller() {
+ super(FacetDecoratorInstaller.TYPE, "help-file");
+ }
+
+ @Override
+ public List<FacetDecorator> createDecorators() {
+ final HelpManagerUsingFiles manager = new HelpManagerUsingFiles(getConfiguration());
+ return Arrays.<FacetDecorator> asList(new HelpFacetDecoratorUsingHelpManager(manager));
+ }
+
+ @Override
+ public List<Class<?>> getTypes() {
+ return listOf(List.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/internal/HelpManagerUsingFiles.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/internal/HelpManagerUsingFiles.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/internal/HelpManagerUsingFiles.java
new file mode 100644
index 0000000..d6f9b89
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/file/internal/HelpManagerUsingFiles.java
@@ -0,0 +1,146 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.help.file.internal;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.progmodel.facetdecorators.help.HelpManagerAbstract;
+
+public class HelpManagerUsingFiles extends HelpManagerAbstract {
+
+ private static final Logger LOG = Logger.getLogger(HelpManagerUsingFiles.class);
+
+ /**
+ * The name of the file used unless overridden with
+ * {@link #setFileName(String)}.
+ */
+ public static final String DEFAULT_FILE_NAME = "help.txt";
+ private static final String CLASS_PREFIX = "c:";
+ private static final String NAME_PREFIX = "m:";
+
+ private String fileName = DEFAULT_FILE_NAME;
+
+ @SuppressWarnings("unused")
+ private final IsisConfiguration configuration;
+
+ public HelpManagerUsingFiles(final IsisConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ public void setFileName(final String fileName) {
+ this.fileName = fileName;
+ }
+
+ @Override
+ public String getHelpText(final Identifier identifier) {
+ BufferedReader reader = null;
+ try {
+ reader = getReader();
+
+ if (reader == null) {
+ return "No help available (no file found)";
+ }
+
+ final String className = CLASS_PREFIX + identifier.getClassName().toLowerCase();
+ final String name = NAME_PREFIX + identifier.getMemberName().toLowerCase();
+
+ final StringBuffer str = new StringBuffer();
+ String line;
+
+ boolean lookingForClass = true;
+ boolean lookingForName = identifier.getMemberName().length() > 0;
+ /*
+ * Read through each line in file.
+ */
+ while ((line = reader.readLine()) != null) {
+ // Skip comments - lines begining with hash
+ if (line.length() > 0 && line.charAt(0) == '#') {
+ continue;
+ }
+
+ /*
+ * Look for class.
+ */
+ if (line.toLowerCase().equals(className)) {
+ lookingForClass = false;
+ continue;
+ }
+
+ if (lookingForClass) {
+ continue;
+ } else if (line.toLowerCase().startsWith(CLASS_PREFIX)) {
+ break;
+ }
+
+ /*
+ * Look for field/method.
+ */
+ if (line.toLowerCase().equals(name)) {
+ lookingForName = false;
+ continue;
+ }
+
+ if (lookingForName) {
+ continue;
+ } else if (line.toLowerCase().startsWith(NAME_PREFIX)) {
+ break;
+ }
+
+ str.append(line);
+ str.append('\n');
+ }
+
+ return str.toString();
+
+ } catch (final FileNotFoundException e) {
+ LOG.error("opening help file", e);
+ return "Failure opening help file: " + e.getMessage();
+ } catch (final IOException e) {
+ LOG.error("reading help file", e);
+ return "Failure reading help file: " + e.getMessage();
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (final IOException ignore) {
+ }
+ }
+ }
+ }
+
+ protected BufferedReader getReader() throws FileNotFoundException {
+ final File file = new File(fileName);
+ if (!file.exists()) {
+ final String message = "No help file found: " + file.getAbsolutePath();
+ LOG.warn(message);
+ return null;
+ }
+
+ return new BufferedReader(new FileReader(file));
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/package-info.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/package-info.java
new file mode 100644
index 0000000..a3f8085
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/help/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ * Help API, utilizing the {@link org.apache.isis.core.metamodel.facetdecorator.FacetDecorator} mechanism..
+ *
+ * <p>
+ * At the time of writing - unlike
+ * authorisation - there is no help-proxy implementation. Therefore for client/server deployments
+ * any help content must be deployed locally.
+ */
+package org.apache.isis.core.progmodel.facetdecorators.help;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nFacetDecorator.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nFacetDecorator.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nFacetDecorator.java
new file mode 100644
index 0000000..1d40793
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nFacetDecorator.java
@@ -0,0 +1,101 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.i18n;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.metamodel.facetdecorator.FacetDecoratorAbstract;
+import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacet;
+import org.apache.isis.core.metamodel.facets.help.HelpFacet;
+import org.apache.isis.core.metamodel.facets.named.NamedFacet;
+import org.apache.isis.core.progmodel.facetdecorators.i18n.internal.DescribedAsFacetWrapI18n;
+import org.apache.isis.core.progmodel.facetdecorators.i18n.internal.HelpFacetWrapI18n;
+import org.apache.isis.core.progmodel.facetdecorators.i18n.internal.NamedFacetWrapI18n;
+
+public class I18nFacetDecorator extends FacetDecoratorAbstract {
+ private final I18nManager i18nManager;
+
+ public I18nFacetDecorator(final I18nManager manager) {
+ i18nManager = manager;
+ }
+
+ @Override
+ public Facet decorate(final Facet facet, final FacetHolder facetHolder) {
+ if (!(facetHolder instanceof IdentifiedHolder)) {
+ return null;
+ }
+
+ final IdentifiedHolder identifiedHolder = (IdentifiedHolder) facetHolder;
+
+ final Class<?> facetType = facet.facetType();
+ if (facetType == NamedFacet.class) {
+ return decorateWithNamedFacet(facet, identifiedHolder);
+ }
+ if (facetType == DescribedAsFacet.class) {
+ return decorateWithDescribedAsFacet(facet, identifiedHolder);
+ }
+ if (facetType == HelpFacet.class) {
+ return decorateWithHelpFacet(facet, identifiedHolder);
+ }
+ return null;
+ }
+
+ private Facet decorateWithNamedFacet(final Facet facet, final IdentifiedHolder identifiedHolder) {
+
+ final Identifier identifier = identifiedHolder.getIdentifier();
+ final String i18nName = i18nManager.getName(identifier);
+ if (i18nName == null) {
+ return null;
+ }
+ final NamedFacetWrapI18n decoratingFacet = new NamedFacetWrapI18n(i18nName, facet.getFacetHolder());
+ identifiedHolder.addFacet(decoratingFacet);
+ return decoratingFacet;
+ }
+
+ private Facet decorateWithDescribedAsFacet(final Facet facet, final IdentifiedHolder identifiedHolder) {
+ final Identifier identifier = identifiedHolder.getIdentifier();
+ final String i18nDescription = i18nManager.getDescription(identifier);
+ if (i18nDescription == null) {
+ return null;
+ }
+ final DescribedAsFacetWrapI18n decoratingFacet = new DescribedAsFacetWrapI18n(i18nDescription, facet.getFacetHolder());
+ identifiedHolder.addFacet(decoratingFacet);
+ return decoratingFacet;
+ }
+
+ private Facet decorateWithHelpFacet(final Facet facet, final IdentifiedHolder identifiedHolder) {
+ final Identifier identifier = identifiedHolder.getIdentifier();
+ final String i18nHelp = i18nManager.getHelp(identifier);
+ if (i18nHelp == null) {
+ return null;
+ }
+ final HelpFacetWrapI18n decoratingFacet = new HelpFacetWrapI18n(i18nHelp, facet.getFacetHolder());
+ identifiedHolder.addFacet(decoratingFacet);
+ return decoratingFacet;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Class<? extends Facet>[] getFacetTypes() {
+ return new Class[] { NamedFacet.class, DescribedAsFacet.class, HelpFacet.class };
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nManager.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nManager.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nManager.java
new file mode 100644
index 0000000..059f7d0
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/I18nManager.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.isis.core.progmodel.facetdecorators.i18n;
+
+import java.util.List;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+
+/**
+ * Authorises the user in the current session view and use members of an object.
+ *
+ * <p>
+ * TODO: allow description and help to be found for parameters
+ */
+public interface I18nManager extends ApplicationScopedComponent {
+
+ /**
+ * Get the localized name for the specified identified action/property.
+ *
+ * <p>
+ * Returns null if no name available.
+ */
+ String getName(Identifier identifier);
+
+ /**
+ * Get the localized description for the specified identified
+ * action/property.
+ *
+ * <p>
+ * Returns null if no description available.
+ */
+ String getDescription(Identifier identifier);
+
+ /**
+ * Get the localized help text for the specified identified action/property.
+ *
+ * <p>
+ * Returns null if no help text available.
+ */
+ String getHelp(Identifier identifier);
+
+ /**
+ * Get the localized parameter names for the specified identified
+ * action/property.
+ *
+ * <p>
+ * Returns null if no parameters are available. Otherwise returns an array
+ * of String objects the size of the number of parameters, where each
+ * element is the localised name for the corresponding parameter, or is null
+ * if no parameter name is available.
+ */
+ List<String> getParameterNames(Identifier identifier);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/DescribedAsFacetWrapI18n.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/DescribedAsFacetWrapI18n.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/DescribedAsFacetWrapI18n.java
new file mode 100644
index 0000000..9fc4fa6
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/DescribedAsFacetWrapI18n.java
@@ -0,0 +1,31 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.i18n.internal;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.describedas.DescribedAsFacetAbstract;
+
+public class DescribedAsFacetWrapI18n extends DescribedAsFacetAbstract {
+
+ public DescribedAsFacetWrapI18n(final String value, final FacetHolder holder) {
+ super(value, holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/HelpFacetWrapI18n.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/HelpFacetWrapI18n.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/HelpFacetWrapI18n.java
new file mode 100644
index 0000000..d570f13
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/HelpFacetWrapI18n.java
@@ -0,0 +1,31 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.i18n.internal;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.help.HelpFacetAbstract;
+
+public class HelpFacetWrapI18n extends HelpFacetAbstract {
+
+ public HelpFacetWrapI18n(final String value, final FacetHolder holder) {
+ super(value, holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/NamedFacetWrapI18n.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/NamedFacetWrapI18n.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/NamedFacetWrapI18n.java
new file mode 100644
index 0000000..a382fd2
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/internal/NamedFacetWrapI18n.java
@@ -0,0 +1,31 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.i18n.internal;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.named.NamedFacetAbstract;
+
+public class NamedFacetWrapI18n extends NamedFacetAbstract {
+
+ public NamedFacetWrapI18n(final String value, final FacetHolder holder) {
+ super(value, holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/I18nDecoratorUsingResourceBundleInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/I18nDecoratorUsingResourceBundleInstaller.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/I18nDecoratorUsingResourceBundleInstaller.java
new file mode 100644
index 0000000..78c91f9
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/I18nDecoratorUsingResourceBundleInstaller.java
@@ -0,0 +1,48 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.i18n.resourcebundle;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.isis.core.commons.config.InstallerAbstract;
+import org.apache.isis.core.metamodel.facetdecorator.FacetDecorator;
+import org.apache.isis.core.metamodel.specloader.FacetDecoratorInstaller;
+import org.apache.isis.core.progmodel.facetdecorators.i18n.I18nFacetDecorator;
+import org.apache.isis.core.progmodel.facetdecorators.i18n.resourcebundle.internal.I18nManagerUsingResourceBundle;
+
+public class I18nDecoratorUsingResourceBundleInstaller extends InstallerAbstract implements FacetDecoratorInstaller {
+
+ public I18nDecoratorUsingResourceBundleInstaller() {
+ super(FacetDecoratorInstaller.TYPE, "resource-i18n");
+ }
+
+ @Override
+ public List<FacetDecorator> createDecorators() {
+ final I18nManagerUsingResourceBundle manager = new I18nManagerUsingResourceBundle(getConfiguration());
+ manager.init();
+ return Arrays.<FacetDecorator> asList(new I18nFacetDecorator(manager));
+ }
+
+ @Override
+ public List<Class<?>> getTypes() {
+ return listOf(List.class); // ie, of List<FacetDecorator>
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/internal/I18nManagerUsingResourceBundle.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/internal/I18nManagerUsingResourceBundle.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/internal/I18nManagerUsingResourceBundle.java
new file mode 100644
index 0000000..e0cb922
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facetdecorators/i18n/resourcebundle/internal/I18nManagerUsingResourceBundle.java
@@ -0,0 +1,182 @@
+/*
+ * 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.isis.core.progmodel.facetdecorators.i18n.resourcebundle.internal;
+
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import com.google.common.collect.Lists;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.progmodel.facetdecorators.i18n.I18nManager;
+
+/**
+ * REVIEW: why isn't there a type for collections also?
+ */
+public class I18nManagerUsingResourceBundle implements I18nManager {
+
+ private static final Logger LOG = Logger.getLogger(I18nManagerUsingResourceBundle.class);
+
+ private static final String BASE_FILE_NAME = "i18n";
+
+ private static final String MEMBER_TYPE_PROPERTY = "property";
+ private static final String MEMBER_TYPE_COLLECTION = "collection";
+ private static final String MEMBER_TYPE_ACTION = "action";
+ private static final String MEMBER_TYPE_PARAMETER = "parameter";
+
+ private static final String TEXT_TYPE_NAME = "name";
+ private static final String TEXT_TYPE_DESCRIPTION = "description";
+ private static final String TEXT_TYPE_HELP = "help";
+
+ private ResourceBundle bundle;
+
+ @SuppressWarnings("unused")
+ private final IsisConfiguration configuration;
+
+ // //////////////////////////////////////////////////////////////
+ // Contructor, init, shutdown
+ // //////////////////////////////////////////////////////////////
+
+ public I18nManagerUsingResourceBundle(final IsisConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public void init() {
+ try {
+ bundle = ResourceBundle.getBundle(BASE_FILE_NAME);
+ } catch (final MissingResourceException e) {
+ LOG.warn("Missing resource bundle: " + e.getMessage());
+ }
+
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Members
+ // //////////////////////////////////////////////////////////////
+
+ @Override
+ public String getName(final Identifier identifier) {
+ return internalizedTextForClassMember(identifier, TEXT_TYPE_NAME);
+ }
+
+ @Override
+ public String getDescription(final Identifier identifier) {
+ return internalizedTextForClassMember(identifier, TEXT_TYPE_DESCRIPTION);
+ }
+
+ @Override
+ public String getHelp(final Identifier identifier) {
+ return internalizedTextForClassMember(identifier, TEXT_TYPE_HELP);
+ }
+
+ private String internalizedTextForClassMember(final Identifier identifier, final String textType) {
+ if (bundle == null) {
+ return null;
+ }
+ final List<String> key = buildMemberTypeKey(identifier, textType);
+ return lookupTextFromBundle(key);
+ }
+
+ private static List<String> buildMemberTypeKey(final Identifier identifier, final String textType) {
+ final List<String> keys = Lists.newArrayList();
+
+ if (identifier.isPropertyOrCollection()) {
+ keys.add(buildMemberTypeKey(identifier, textType, MEMBER_TYPE_PROPERTY));
+ keys.add(buildMemberTypeKey(identifier, textType, MEMBER_TYPE_COLLECTION));
+ } else {
+ keys.add(buildMemberTypeKey(identifier, textType, MEMBER_TYPE_ACTION));
+ }
+ return keys;
+ }
+
+ private static String buildMemberTypeKey(final Identifier identifier, final String textType, final String memberType) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(identifier.getClassName()).append(".");
+ sb.append(memberType);
+ final String memberName = identifier.getMemberName();
+ if (!StringUtils.isNullOrEmpty(memberName)) {
+ sb.append(".").append(memberName);
+ }
+ sb.append(".").append(textType);
+ return sb.toString();
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Parameters
+ // //////////////////////////////////////////////////////////////
+
+ @Override
+ public List<String> getParameterNames(final Identifier identifier) {
+ return internalizedTextForParameter(identifier, TEXT_TYPE_NAME);
+ }
+
+ private List<String> internalizedTextForParameter(final Identifier identifier, final String textType) {
+ if (bundle == null) {
+ return null;
+ }
+ final List<String> internalizedText = Lists.newArrayList();
+ final List<String> memberParameterNames = identifier.getMemberParameterNames();
+ int paramNum = 0;
+ for (@SuppressWarnings("unused")
+ final String dummy : memberParameterNames) {
+ final String key = buildParameterTypeKey(identifier, textType, paramNum);
+ internalizedText.add(lookupTextFromBundle(key));
+ paramNum++;
+ }
+ return internalizedText;
+ }
+
+ private static String buildParameterTypeKey(final Identifier identifier, final String textType, final int paramNum) {
+ return identifier.getClassName() + "." + MEMBER_TYPE_ACTION + "." + identifier.getMemberName() + "." + MEMBER_TYPE_PARAMETER + (paramNum + 1) + "." + textType;
+ }
+
+ // //////////////////////////////////////////////////////////////
+ // Helpers
+ // //////////////////////////////////////////////////////////////
+
+ private String lookupTextFromBundle(final List<String> keys) {
+ for (final String key : keys) {
+ final String text = lookupTextFromBundle(key);
+ if (text != null) {
+ return text;
+ }
+ }
+ return null;
+ }
+
+ private String lookupTextFromBundle(final String key) {
+ try {
+ return bundle.getString(key);
+ } catch (final MissingResourceException e) {
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/CollectionUtils.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/CollectionUtils.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/CollectionUtils.java
new file mode 100644
index 0000000..9a9757b
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/CollectionUtils.java
@@ -0,0 +1,43 @@
+/*
+ * 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.isis.core.progmodel.facets;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public final class CollectionUtils {
+ private CollectionUtils() {
+ }
+
+ public static Object[] getCollectionAsObjectArray(final Object option, final ObjectSpecification spec, final AdapterManager adapterMap) {
+ final ObjectAdapter collection = adapterMap.adapterFor(option);
+ final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collection);
+ final Object[] optionArray = new Object[facet.size(collection)];
+ int j = 0;
+ for (final ObjectAdapter nextElement : facet.iterable(collection)) {
+ optionArray[j++] = nextElement.getObject();
+ }
+ return optionArray;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodFinderUtils.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodFinderUtils.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodFinderUtils.java
new file mode 100644
index 0000000..f3dcfcc
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodFinderUtils.java
@@ -0,0 +1,180 @@
+/**
+ * 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.isis.core.progmodel.facets;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.facetapi.MethodRemover;
+import org.apache.isis.core.metamodel.methodutils.MethodScope;
+
+public final class MethodFinderUtils {
+
+ private MethodFinderUtils() {
+ }
+
+ public static Method findMethodWithOrWithoutParameters(final Class<?> type, final MethodScope classMethod, final String name, final Class<?> returnType, final Class<?>[] paramTypes) {
+ Method method = MethodFinderUtils.findMethod(type, classMethod, name, returnType, paramTypes);
+ if (method == null) {
+ method = MethodFinderUtils.findMethod(type, classMethod, name, returnType, MethodPrefixBasedFacetFactoryAbstract.NO_PARAMETERS_TYPES);
+ }
+ return method;
+ }
+
+ /**
+ * Returns a specific public methods that: have the specified prefix; have
+ * the specified return type, or void, if canBeVoid is true; and has the
+ * specified number of parameters. If the returnType is specified as null
+ * then the return type is ignored.
+ *
+ * @param paramTypes
+ * the set of parameters the method should have, if null then is
+ * ignored
+ */
+ public static Method findMethod(final Class<?> type, final MethodScope methodScope, final String name, final Class<?> returnType, final Class<?>[] paramTypes) {
+ Method method;
+ try {
+ method = type.getMethod(name, paramTypes);
+ } catch (final SecurityException e) {
+ return null;
+ } catch (final NoSuchMethodException e) {
+ return null;
+ }
+
+ final int modifiers = method.getModifiers();
+
+ // check for public modifier
+ if (!Modifier.isPublic(modifiers)) {
+ return null;
+ }
+
+ // check for scope modifier
+ if (!methodScope.matchesScopeOf(method)) {
+ return null;
+ }
+
+ // check for name
+ if (!method.getName().equals(name)) {
+ return null;
+ }
+
+ // check for return type
+ if (returnType != null && returnType != method.getReturnType()) {
+ return null;
+ }
+
+ // check params (if required)
+ if (paramTypes != null) {
+ final Class<?>[] parameterTypes = method.getParameterTypes();
+ if (paramTypes.length != parameterTypes.length) {
+ return null;
+ }
+
+ for (int c = 0; c < paramTypes.length; c++) {
+ if ((paramTypes[c] != null) && (paramTypes[c] != parameterTypes[c])) {
+ return null;
+ }
+ }
+ }
+
+ return method;
+ }
+
+ protected static boolean doesNotMatchScope(final MethodScope methodScope, final Method method) {
+ return methodScope.doesNotMatchScope(method);
+ }
+
+ public static Method findMethod(final Class<?> type, final MethodScope methodScope, final String name, final Class<?> returnType) {
+ try {
+ final Method[] methods = type.getMethods();
+ for (final Method method2 : methods) {
+ final Method method = method2;
+ final int modifiers = method.getModifiers();
+ // check for public modifier
+ if (!Modifier.isPublic(modifiers)) {
+ continue;
+ }
+
+ // check correct scope (static vs instance)
+ if (!methodScope.matchesScopeOf(method)) {
+ continue;
+ }
+
+ // check for name
+ if (!method.getName().equals(name)) {
+ continue;
+ }
+
+ // check for return type
+ if (returnType != null && returnType != method.getReturnType()) {
+ continue;
+ }
+ return method;
+ }
+ } catch (final SecurityException e) {
+ return null;
+ }
+ return null;
+ }
+
+ public static List<Method> findMethodsWithAnnotation(final Class<?> type, final MethodScope methodScope, final Class<? extends Annotation> annotationClass) {
+
+ final List<Method> methods = new ArrayList<Method>();
+
+ // Validate arguments
+ if ((type == null) || (methodScope == null) || (annotationClass == null)) {
+ throw new IllegalArgumentException("One or more arguments are 'null' valued");
+ }
+
+ // Find methods annotated with the specified annotation
+ for (final Method method : type.getMethods()) {
+ if (!methodScope.matchesScopeOf(method)) {
+ continue;
+ }
+
+ if (method.isAnnotationPresent(annotationClass)) {
+ methods.add(method);
+ }
+ }
+
+ return methods;
+ }
+
+ public static void removeMethod(final MethodRemover methodRemover, final Method method) {
+ if (methodRemover != null && method != null) {
+ methodRemover.removeMethod(method);
+ }
+ }
+
+ public static Class<?>[] paramTypesOrNull(final Class<?> type) {
+ return type == null ? null : new Class[] { type };
+ }
+
+ public static boolean allParametersOfSameType(final Class<?>[] params) {
+ final Class<?> firstParam = params[0];
+ for (int i = 1; i < params.length; i++) {
+ if (params[i] != firstParam) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixBasedFacetFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixBasedFacetFactoryAbstract.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixBasedFacetFactoryAbstract.java
new file mode 100644
index 0000000..3d2d73a
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixBasedFacetFactoryAbstract.java
@@ -0,0 +1,83 @@
+/*
+ * 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.isis.core.progmodel.facets;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.MethodPrefixBasedFacetFactory;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer.Contributed;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+
+public abstract class MethodPrefixBasedFacetFactoryAbstract extends FacetFactoryAbstract implements MethodPrefixBasedFacetFactory {
+
+ private final List<String> prefixes;
+
+ protected static final Object[] NO_PARAMETERS = new Object[0];
+ protected static final Class<?>[] NO_PARAMETERS_TYPES = new Class<?>[0];
+
+ private final OrphanValidation orphanValidation;
+
+ protected enum OrphanValidation {
+ VALIDATE,
+ DONT_VALIDATE
+ }
+
+ public MethodPrefixBasedFacetFactoryAbstract(final List<FeatureType> featureTypes, OrphanValidation orphanValidation, final String... prefixes) {
+ super(featureTypes);
+ this.orphanValidation = orphanValidation;
+ this.prefixes = Collections.unmodifiableList(Arrays.asList(prefixes));
+ }
+
+ @Override
+ public List<String> getPrefixes() {
+ return prefixes;
+ }
+
+ @Override
+ public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
+ if(orphanValidation == OrphanValidation.DONT_VALIDATE) {
+ return;
+ }
+ metaModelValidator.add(new MetaModelValidatorVisiting(new MetaModelValidatorVisiting.Visitor() {
+
+ @Override
+ public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+ List<ObjectAction> objectActions = objectSpec.getObjectActions(Contributed.EXCLUDED);
+ for (ObjectAction objectAction : objectActions) {
+ for (String prefix : prefixes) {
+ if (objectAction.getId().startsWith(prefix)) {
+ validationFailures.add("%s#%s has prefix %s, has probably been orphaned. If not an orphan, then rename and use @Named annotation", objectSpec.getIdentifier().getClassName(), objectAction.getId(), prefix);
+ }
+ }
+ }
+ return true;
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixConstants.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixConstants.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixConstants.java
new file mode 100644
index 0000000..1426d3e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/MethodPrefixConstants.java
@@ -0,0 +1,68 @@
+/**
+ * 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.isis.core.progmodel.facets;
+
+import org.apache.isis.core.commons.lang.StringUtils;
+
+public class MethodPrefixConstants {
+
+ public static final String GET_PREFIX = "get";
+ public static final String IS_PREFIX = "is";
+ public static final String SET_PREFIX = "set";
+ public static final String CLEAR_PREFIX = "clear";
+ public static final String MODIFY_PREFIX = "modify";
+ public static final String ADD_TO_PREFIX = "addTo";
+ public static final String REMOVE_FROM_PREFIX = "removeFrom";
+
+ public static final String NAME_PREFIX = "name";
+ public static final String DESCRIPTION_PREFIX = "description";
+ public static final String OPTIONAL_PREFIX = "optional";
+
+ public static final String DEFAULT_PREFIX = "default";
+ public static final String CHOICES_PREFIX = "choices";
+
+ public static final String HIDE_PREFIX = "hide";
+ public static final String ALWAYS_HIDE_PREFIX = "alwaysHide";
+
+ public static final String DISABLE_PREFIX = "disable";
+ public static final String PROTECT_PREFIX = "protect";
+
+ public static final String VALIDATE_PREFIX = "validate";
+ public static final String VALIDATE_ADD_TO_PREFIX = VALIDATE_PREFIX + ADD_TO_PREFIX;
+ public static final String VALIDATE_ADD_TO_PREFIX_2 = VALIDATE_PREFIX + StringUtils.capitalize(ADD_TO_PREFIX);
+ public static final String VALIDATE_REMOVE_FROM_PREFIX = VALIDATE_PREFIX + REMOVE_FROM_PREFIX;
+ public static final String VALIDATE_REMOVE_FROM_PREFIX_2 = VALIDATE_PREFIX + StringUtils.capitalize(REMOVE_FROM_PREFIX);
+
+ public static final String FIELD_PREFIX = "field";
+ public static final String ACTION_PREFIX = "action";
+
+ public static final String CREATED_PREFIX = "created";
+ public static final String LOADED_PREFIX = "loaded";
+ public static final String LOADING_PREFIX = "loading";
+ public static final String SAVED_PREFIX = "saved";
+ public static final String SAVING_PREFIX = "saving";
+ public static final String PERSISTED_PREFIX = "persisted";
+ public static final String PERSISTING_PREFIX = "persisting";
+ public static final String DELETED_PREFIX = "deleted";
+ public static final String DELETING_PREFIX = "deleting";
+ public static final String REMOVED_PREFIX = "removed";
+ public static final String REMOVING_PREFIX = "removing";
+ public static final String UPDATED_PREFIX = "updated";
+ public static final String UPDATING_PREFIX = "updating";
+ public static final String SINGULAR_NAME = "singularName";
+
+}