feature[TW18345]: ICD - Add computed fields to artifact types

Change-Id: Ib2bdfb4009813cd2cf7af31cf972efdc4d6feeb7
Signed-off-by: Stephen J. Molaro <stephen.j.molaro@boeing.com>
diff --git a/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF
index f5fa6e9..80c09bc 100644
--- a/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF
@@ -51,6 +51,7 @@
  org.eclipse.osee.framework.core.access,
  org.eclipse.osee.framework.core.applicability,
  org.eclipse.osee.framework.core.data,
+ org.eclipse.osee.framework.core.data.computed,
  org.eclipse.osee.framework.core.enums,
  org.eclipse.osee.framework.core.enums.token,
  org.eclipse.osee.framework.core.event,
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ArtifactTypeToken.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ArtifactTypeToken.java
index 6663c82..36315a0 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ArtifactTypeToken.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ArtifactTypeToken.java
@@ -48,6 +48,10 @@
 
    <T> T getAttributeDefault(AttributeTypeGeneric<T> attributeType);
 
+   List<ComputedCharacteristicToken<?>> getValidComputedCharacteristics();
+
+   <T> boolean isComputedCharacteristicValid(ComputedCharacteristicToken<T> computedCharacteristic);
+
    default boolean inheritsFromAny(Collection<ArtifactTypeToken> artTypes) {
       for (ArtifactTypeToken inheritType : artTypes) {
          if (this.inheritsFrom(inheritType)) {
@@ -193,6 +197,23 @@
          }
 
          @Override
+         public List<ComputedCharacteristicToken<?>> getValidComputedCharacteristics() {
+            List<ComputedCharacteristicToken<?>> validCharacteristics = new ArrayList<>();
+            for (ComputedCharacteristicToken<?> computedCharacteristic : attributeTypes.getComputedCharacteristics()) {
+               if (isComputedCharacteristicValid(computedCharacteristic)) {
+                  validCharacteristics.add(computedCharacteristic);
+               }
+            }
+            return validCharacteristics;
+         }
+
+         @Override
+         public <T> boolean isComputedCharacteristicValid(ComputedCharacteristicToken<T> computedCharacteristic) {
+            return attributeTypes.getComputedCharacteristics().contains(
+               computedCharacteristic) && computedCharacteristic.isMultiplicityValid(this);
+         }
+
+         @Override
          public String getName() {
             String name = super.getName();
             if (namespace.notEqual(NamespaceToken.OSEE) && !superTypes.isEmpty()) {
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeMultiplicity.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeMultiplicity.java
index 2238b41..bfdf96d 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeMultiplicity.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeMultiplicity.java
@@ -27,6 +27,7 @@
 public final class AttributeMultiplicity extends ConcurrentHashMap<AttributeTypeToken, ArtifactTypeAttributeTypeMetaData<?>> {
    private static final long serialVersionUID = 1L;
    private final ArtifactTypeToken artifactType;
+   private final List<ComputedCharacteristicToken<?>> computedCharacteristics = new ArrayList<>();
 
    public AttributeMultiplicity(Long id, NamespaceToken namespace, String name, boolean isAbstract, List<ArtifactTypeToken> superTypes) {
       ArtifactTypeToken artifactType = ArtifactTypeToken.create(id, namespace, name, isAbstract, this, superTypes);
@@ -98,6 +99,15 @@
       return this;
    }
 
+   public <T> AttributeMultiplicity computed(ComputedCharacteristic<T> computedCharacteristic) {
+      computedCharacteristics.add(computedCharacteristic);
+      return this;
+   }
+
+   public List<ComputedCharacteristicToken<?>> getComputedCharacteristics() {
+      return computedCharacteristics;
+   }
+
    public Integer getMinimum(AttributeTypeToken attributeType) {
       return getMultiplicity(attributeType).matches(Multiplicity.ANY, Multiplicity.ZERO_OR_ONE) ? 0 : 1;
    }
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeTypeToken.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeTypeToken.java
index e82e77b..cc0bddb 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeTypeToken.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/AttributeTypeToken.java
@@ -91,10 +91,6 @@
       return false;
    }
 
-   default boolean isObject() {
-      return false;
-   }
-
    default boolean isInputStream() {
       return false;
    }
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristic.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristic.java
new file mode 100644
index 0000000..2f07c68
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristic.java
@@ -0,0 +1,89 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.osee.framework.core.data;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.osee.framework.jdk.core.type.NamedIdDescription;
+
+/**
+ * @author Stephen J. Molaro
+ */
+public abstract class ComputedCharacteristic<T> extends NamedIdDescription implements ComputedCharacteristicToken<T> {
+
+   private final TaggerTypeToken taggerType;
+   private final NamespaceToken namespace;
+   protected final List<AttributeTypeGeneric<T>> attributeTypes;
+   protected final Set<DisplayHint> displayHints;
+
+   public ComputedCharacteristic(Long id, String name, TaggerTypeToken taggerType, NamespaceToken namespace, String description, List<AttributeTypeGeneric<T>> attributeTypes, Set<DisplayHint> displayHints) {
+      super(id, name, description);
+      this.namespace = namespace;
+      this.taggerType = taggerType;
+      this.attributeTypes = attributeTypes;
+      this.displayHints = displayHints;
+   }
+
+   public ComputedCharacteristic(Long id, String name, TaggerTypeToken taggerType, NamespaceToken namespace, String description, List<AttributeTypeGeneric<T>> attributeTypes) {
+      this(id, name, taggerType, namespace, description, attributeTypes, Collections.emptySet());
+   }
+
+   public ComputedCharacteristic(Long id, String name, TaggerTypeToken taggerType, NamespaceToken namespace, String description, List<AttributeTypeGeneric<T>> attributeTypes, DisplayHint... displayHints) {
+      this(id, name, taggerType, namespace, description, attributeTypes,
+         org.eclipse.osee.framework.jdk.core.util.Collections.asHashSet(displayHints));
+   }
+
+   @Override
+   public List<AttributeTypeGeneric<T>> getAttributeTypes() {
+      return attributeTypes;
+   }
+
+   @Override
+   public String getMediaType() {
+      return MediaType.TEXT_PLAIN;
+   }
+
+   @Override
+   public TaggerTypeToken getTaggerType() {
+      return taggerType;
+   }
+
+   @Override
+   public NamespaceToken getNamespace() {
+      return namespace;
+   }
+
+   @Override
+   public Set<DisplayHint> getDisplayHints() {
+      return displayHints;
+   }
+
+   /**
+    * return true in the case that the computed type only has two valid values. Should be used in isMultiplicityValid()
+    * if only two values are desired.
+    */
+   private boolean exactlyTwoValues(ArtifactTypeToken artifactType) {
+      if (attributeTypes.size() > 2) {
+         return false;
+      }
+      for (AttributeTypeGeneric<T> attributeType : attributeTypes) {
+         if (artifactType.getMax(attributeType) > 1) {
+            return false;
+         }
+      }
+      return true;
+   }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicDesign.adoc b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicDesign.adoc
index 4a5a081..257b310 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicDesign.adoc
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicDesign.adoc
@@ -23,9 +23,9 @@
 
 The computed characteristic value shall not be directly modifiable (cannot be set through functionality like setSoleAttribute()). The only method to setting this value will be through calculations done using the relevant attribute types. The computed Characteristic will be recalculated every time it is obtained via the API.
 
-Compile time checking will be used to ensure the compatability of the attribute type's parameterized type (e.g. Integer, String).
+Compile time checking will be used to ensure the compatibility of the attribute type's parameterized type (e.g. Integer, String).
 
-At runtime, during token definition, the multiplicity of the supplied attribute type(s) will be checked for compatability with the predefined calculation. Examples for the predefined calculations as follows:
+At runtime, during token definition, the multiplicity of the supplied attribute type(s) will be checked for compatibility with the predefined calculation. Examples for the predefined calculations as follows:
 	Rate, Ratio, Delta, Quotient - Provided attribute types must have max 1 multiplicity
 	Product, Sum, Average - Provided attributes types can have any multiplicity
 
@@ -35,7 +35,7 @@
 
 == Computed Characteristic Details/Design
 
-Computed Characteristic is a interface that extends NamedId. Contains a calculate function for doing arbitrarily complex calculations. Results can be obtained through a getComputedCharacteristic(ComputedCharacteristicToken<T>) method in ArtifactReadable. Generics will be used in order to ensure supplied attribute types have compatible parameterized types. (Generic <T> represents the specific calculation object being utilized (e.g. LengthCharacteristic)). This will be done by utilizing a validity check method .isComputedCharacteristicValid() on ArtifaceReadable.
+Computed Characteristic is a interface that extends NamedId. Contains a calculate function for doing arbitrarily complex calculations. Results can be obtained through a getComputedCharacteristic(ComputedCharacteristicToken<T>) method in ArtifactReadable. Generics will be used in order to ensure supplied attribute types have compatible parameterized types. (Generic <T> represents the specific calculation object being utilized (e.g. LengthCharacteristic)). This will be done by utilizing a validity check method .isComputedCharacteristicValid() in ArtifaceReadable.
 
 == Declaring a Computed Characteristic
 
@@ -55,7 +55,9 @@
 
 == Additional Tasks
 
-Update new search mechanism for computed characteristics
+	Update new search mechanism for computed characteristics
+	Adding engineering units to attribute types
+	CompoundComputedCharacteristic
 
 == Considerations for the future
 
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicToken.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicToken.java
new file mode 100644
index 0000000..f68e830
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/ComputedCharacteristicToken.java
@@ -0,0 +1,70 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.osee.framework.core.data;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.osee.framework.core.data.computed.ComputedCharacteristicSentinel;
+import org.eclipse.osee.framework.jdk.core.type.FullyNamed;
+import org.eclipse.osee.framework.jdk.core.type.HasDescription;
+import org.eclipse.osee.framework.jdk.core.type.Id;
+import org.eclipse.osee.framework.jdk.core.type.Named;
+import org.eclipse.osee.framework.jdk.core.type.NamedId;
+
+/**
+ * @author Stephen J. Molaro
+ */
+
+public interface ComputedCharacteristicToken<T> extends FullyNamed, HasDescription, NamedId {
+
+   public static final ComputedCharacteristic<?> SENTINEL = valueOf(Id.SENTINEL, Named.SENTINEL, "");
+
+   static final String APPLICATION_ZIP = "application/zip";
+   static final String TEXT_CALENDAR = "text/calendar";
+   static final String TEXT_URI_LIST = "text/uri-list";
+   static final String APPLICATION_MSWORD = "application/msword";
+   static final String MODEL_OSEE = "model/osee";
+   static final String IMAGE = "image/*";
+
+   boolean isMultiplicityValid(ArtifactTypeToken artifactType);
+
+   T calculate(List<T> attributeValues);
+
+   List<AttributeTypeGeneric<T>> getAttributeTypes();
+
+   String getMediaType();
+
+   Set<DisplayHint> getDisplayHints();
+
+   default NamespaceToken getNamespace() {
+      return NamespaceToken.SENTINEL;
+   }
+
+   default TaggerTypeToken getTaggerType() {
+      return TaggerTypeToken.SENTINEL;
+   }
+
+   default boolean isTaggable() {
+      return getTaggerType().isValid();
+   }
+
+   static @NonNull ComputedCharacteristic<?> valueOf(Long id, String name, String description) {
+      List<AttributeTypeGeneric<Object>> SentinalList = new ArrayList<>();
+      return new ComputedCharacteristicSentinel(Id.SENTINEL, Named.SENTINEL, TaggerTypeToken.SENTINEL,
+         NamespaceToken.OSEE, "", SentinalList);
+   }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/OrcsTypeTokens.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/OrcsTypeTokens.java
index 9b299f0..ff772d1 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/OrcsTypeTokens.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/OrcsTypeTokens.java
@@ -14,6 +14,7 @@
 package org.eclipse.osee.framework.core.data;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import javax.ws.rs.core.MediaType;
 import org.eclipse.jdt.annotation.NonNull;
@@ -24,6 +25,7 @@
 import org.eclipse.osee.framework.jdk.core.type.ChainingArrayList;
 import org.eclipse.osee.framework.jdk.core.type.OseeArgumentException;
 import org.eclipse.osee.framework.jdk.core.type.QuinFunction;
+import org.eclipse.osee.framework.jdk.core.type.SexFunction;
 
 /**
  * OSEE type token providers should instantiate a static instance of this class and call the add methods for each type
@@ -35,6 +37,8 @@
    private final List<ArtifactTypeToken> artifactTypes = new ArrayList<>();
    private final ChainingArrayList<@NonNull AttributeTypeGeneric<?>> attributeTypes = new ChainingArrayList<>();
    private final ChainingArrayList<@NonNull RelationTypeToken> relationTypes = new ChainingArrayList<>();
+   private final ChainingArrayList<@NonNull ComputedCharacteristic<?>> computedCharacteristics =
+      new ChainingArrayList<>();
    private final List<OrcsTypeJoin<?, ?>> orcsTypeJoins = new ArrayList<>();
    private final NamespaceToken namespace;
 
@@ -291,6 +295,20 @@
    }
 
    /**
+    * Methods for creating Computed Characteristics
+    */
+
+   public <T, U extends ComputedCharacteristic<T>> U createComp(SexFunction<Long, String, TaggerTypeToken, NamespaceToken, String, List<AttributeTypeGeneric<T>>, U> computationCharacteristicConstructor, Long id, String name, String description, AttributeTypeGeneric<T>... typesToCompute) {
+      return computedCharacteristics.addAndReturn(computationCharacteristicConstructor.apply(id, name,
+         TaggerTypeToken.PlainTextTagger, namespace, description, Arrays.asList(typesToCompute)));
+   }
+
+   public <T, U extends ComputedCharacteristic<T>> U createCompNoTag(SexFunction<Long, String, TaggerTypeToken, NamespaceToken, String, List<AttributeTypeGeneric<T>>, U> computationCharacteristicConstructor, Long id, String name, String description, AttributeTypeGeneric<T>... typesToCompute) {
+      return computedCharacteristics.addAndReturn(computationCharacteristicConstructor.apply(id, name,
+         TaggerTypeToken.SENTINEL, namespace, description, Arrays.asList(typesToCompute)));
+   }
+
+   /**
     * return the default tagger for the given mediaType
     */
    public static TaggerTypeToken determineTaggerType(String mediaType) {
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/computed/ComputedCharacteristicSentinel.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/computed/ComputedCharacteristicSentinel.java
new file mode 100644
index 0000000..eb73442
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/data/computed/ComputedCharacteristicSentinel.java
@@ -0,0 +1,41 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.osee.framework.core.data.computed;
+
+import java.util.List;
+import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
+import org.eclipse.osee.framework.core.data.AttributeTypeGeneric;
+import org.eclipse.osee.framework.core.data.ComputedCharacteristic;
+import org.eclipse.osee.framework.core.data.NamespaceToken;
+import org.eclipse.osee.framework.core.data.TaggerTypeToken;
+
+/**
+ * @author Stephen J. Molaro
+ */
+public final class ComputedCharacteristicSentinel extends ComputedCharacteristic<Object> {
+
+   public ComputedCharacteristicSentinel(Long id, String name, TaggerTypeToken taggerType, NamespaceToken namespace, String description, List<AttributeTypeGeneric<Object>> typesToCompute) {
+      super(id, name, taggerType, namespace, description, typesToCompute);
+   }
+
+   @Override
+   public boolean isMultiplicityValid(ArtifactTypeToken artifactType) {
+      return true;
+   }
+
+   @Override
+   public Object calculate(List<Object> attributeValues) {
+      return 0;
+   }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/QuinFunction.java b/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/QuinFunction.java
index 744348e..fee4a50 100644
--- a/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/QuinFunction.java
+++ b/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/QuinFunction.java
@@ -25,8 +25,11 @@
     *
     * @param t the first function argument
     * @param u the second function argument
+    * @param v the third function argument
+    * @param w the fourth function argument
+    * @param x the fifth function argument
     * @return the function result
     */
    R apply(T t, U u, V v, W w, X x);
 
-}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/SexFunction.java b/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/SexFunction.java
new file mode 100644
index 0000000..ba5f8a7
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.jdk.core/src/org/eclipse/osee/framework/jdk/core/type/SexFunction.java
@@ -0,0 +1,36 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Boeing - initial API and implementation
+ **********************************************************************/
+
+package org.eclipse.osee.framework.jdk.core.type;
+
+/**
+ * @author Stephen J. Molaro
+ */
+
+@FunctionalInterface
+public interface SexFunction<T, U, V, W, X, Y, R> {
+
+   /**
+    * Applies this function to the given arguments.
+    *
+    * @param t the first function argument
+    * @param u the second function argument
+    * @param v the third function argument
+    * @param w the fourth function argument
+    * @param x the fifth function argument
+    * @param y the sixth function argument
+    * @return the function result
+    */
+   R apply(T t, U u, V v, W w, X x, Y y);
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/attribute/AttributeFactory.java b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/attribute/AttributeFactory.java
index 405c5fa..b598974 100644
--- a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/attribute/AttributeFactory.java
+++ b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/attribute/AttributeFactory.java
@@ -103,7 +103,7 @@
          attribute = new ArtifactReferenceAttribute(id);
       } else if (attributeType.isBranchId()) {
          attribute = new BranchReferenceAttribute(id);
-      } else if (attributeType.isObject()) {
+      } else if (attributeType.isJavaObject()) {
          attribute = new JavaObjectAttribute(id);
       } else if (attributeType.isInputStream()) {
          attribute = new CompressedContentAttribute(id);
diff --git a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/proxy/impl/ArtifactReadOnlyImpl.java b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/proxy/impl/ArtifactReadOnlyImpl.java
index 10affd4..b524450 100644
--- a/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/proxy/impl/ArtifactReadOnlyImpl.java
+++ b/plugins/org.eclipse.osee.orcs.core/src/org/eclipse/osee/orcs/core/internal/proxy/impl/ArtifactReadOnlyImpl.java
@@ -23,9 +23,11 @@
 import org.eclipse.osee.framework.core.data.ArtifactTypeId;
 import org.eclipse.osee.framework.core.data.ArtifactTypeToken;
 import org.eclipse.osee.framework.core.data.AttributeId;
+import org.eclipse.osee.framework.core.data.AttributeTypeGeneric;
 import org.eclipse.osee.framework.core.data.AttributeTypeId;
 import org.eclipse.osee.framework.core.data.AttributeTypeToken;
 import org.eclipse.osee.framework.core.data.BranchToken;
+import org.eclipse.osee.framework.core.data.ComputedCharacteristicToken;
 import org.eclipse.osee.framework.core.data.IRelationLink;
 import org.eclipse.osee.framework.core.data.RelationTypeSide;
 import org.eclipse.osee.framework.core.data.RelationTypeToken;
@@ -37,6 +39,7 @@
 import org.eclipse.osee.framework.core.enums.RelationSide;
 import org.eclipse.osee.framework.core.exception.AttributeDoesNotExist;
 import org.eclipse.osee.framework.jdk.core.type.Id;
+import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
 import org.eclipse.osee.framework.jdk.core.type.Pair;
 import org.eclipse.osee.framework.jdk.core.type.ResultSet;
 import org.eclipse.osee.framework.jdk.core.type.ResultSetList;
@@ -219,6 +222,20 @@
    }
 
    @Override
+   public <T> T getComputedCharacteristicValue(ComputedCharacteristicToken<T> computedCharacteristic) {
+      List<T> attributeValues = new ArrayList<T>();
+      if (!artifactType.isComputedCharacteristicValid(computedCharacteristic)) {
+         throw new OseeCoreException(
+            "Attribute Types on Artifact Type %s do not have valid multiplicity for computed characteristic %s",
+            artifactType.getName(), computedCharacteristic.getName());
+      }
+      for (AttributeTypeGeneric<T> attributeType : computedCharacteristic.getAttributeTypes()) {
+         attributeValues.addAll(getAttributeValues(attributeType));
+      }
+      return computedCharacteristic.calculate(attributeValues);
+   }
+
+   @Override
    public int getMaximumRelationAllowed(RelationTypeSide typeAndSide) {
       RelationTypeToken type = typeAndSide.getRelationType();
       RelationSide side = whichSideAmIOn(typeAndSide);
diff --git a/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadable.java b/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadable.java
index 864e48b..f3634a2 100644
--- a/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadable.java
+++ b/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadable.java
@@ -25,6 +25,7 @@
 import org.eclipse.osee.framework.core.data.AttributeId;
 import org.eclipse.osee.framework.core.data.AttributeTypeEnum;
 import org.eclipse.osee.framework.core.data.AttributeTypeToken;
+import org.eclipse.osee.framework.core.data.ComputedCharacteristicToken;
 import org.eclipse.osee.framework.core.data.IRelationLink;
 import org.eclipse.osee.framework.core.data.RelationTypeSide;
 import org.eclipse.osee.framework.core.data.RelationTypeToken;
@@ -96,6 +97,11 @@
    }
 
    ////////////////////
+
+   <T> T getComputedCharacteristicValue(ComputedCharacteristicToken<T> computedCharacteristic);
+
+   ////////////////////
+
    int getMaximumRelationAllowed(RelationTypeSide relationTypeSide);
 
    Collection<RelationTypeToken> getValidRelationTypes();
@@ -168,4 +174,5 @@
    List<ArtifactReadable> getRelatedList(RelationTypeSide relationTypeSide);
 
    <T> List<T> getAttributeValues(AttributeTypeToken attributeType, DeletionFlag deletionFlag);
+
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadableImpl.java b/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadableImpl.java
index 3ede5d7..1f3f001 100644
--- a/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadableImpl.java
+++ b/plugins/org.eclipse.osee.orcs/src/org/eclipse/osee/orcs/data/ArtifactReadableImpl.java
@@ -14,6 +14,7 @@
 package org.eclipse.osee.orcs.data;
 
 import static org.eclipse.osee.framework.core.enums.CoreAttributeTypes.Name;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -27,6 +28,7 @@
 import org.eclipse.osee.framework.core.data.AttributeTypeGeneric;
 import org.eclipse.osee.framework.core.data.AttributeTypeToken;
 import org.eclipse.osee.framework.core.data.BranchToken;
+import org.eclipse.osee.framework.core.data.ComputedCharacteristicToken;
 import org.eclipse.osee.framework.core.data.IAttribute;
 import org.eclipse.osee.framework.core.data.IRelationLink;
 import org.eclipse.osee.framework.core.data.RelationTypeSide;
@@ -41,6 +43,7 @@
 import org.eclipse.osee.framework.core.exception.MultipleAttributesExist;
 import org.eclipse.osee.framework.jdk.core.type.BaseId;
 import org.eclipse.osee.framework.jdk.core.type.HashCollection;
+import org.eclipse.osee.framework.jdk.core.type.OseeCoreException;
 import org.eclipse.osee.framework.jdk.core.type.OseeStateException;
 import org.eclipse.osee.framework.jdk.core.type.ResultSet;
 import org.eclipse.osee.framework.jdk.core.type.ResultSetList;
@@ -265,6 +268,20 @@
    }
 
    @Override
+   public <T> T getComputedCharacteristicValue(ComputedCharacteristicToken<T> computedCharacteristic) {
+      List<T> attributeValues = new ArrayList<T>();
+      if (!artifactType.isComputedCharacteristicValid(computedCharacteristic)) {
+         throw new OseeCoreException(
+            "Attribute Types on Artifact Type %s do not have valid multiplicity for computed characteristic %s",
+            artifactType.getName(), computedCharacteristic.getName());
+      }
+      for (AttributeTypeGeneric<T> attributeType : computedCharacteristic.getAttributeTypes()) {
+         attributeValues.addAll(getAttributeValues(attributeType));
+      }
+      return computedCharacteristic.calculate(attributeValues);
+   }
+
+   @Override
    public int getMaximumRelationAllowed(RelationTypeSide relationTypeSide) {
       throw new UnsupportedOperationException();
    }