package ecologylab.bigsemantics.metametadata; import java.util.ArrayList; import java.util.List; import ecologylab.bigsemantics.html.utils.StringBuilderUtils; import ecologylab.bigsemantics.metadata.MetadataClassDescriptor; import ecologylab.bigsemantics.metadata.MetadataFieldDescriptor; import ecologylab.bigsemantics.metadata.scalar.types.MetadataScalarType; import ecologylab.bigsemantics.metametadata.exceptions.MetaMetadataException; import ecologylab.serialization.FieldType; import ecologylab.serialization.MetaInformation; import ecologylab.serialization.SimplTypesScope; import ecologylab.serialization.annotations.Hint; import ecologylab.serialization.annotations.simpl_collection; import ecologylab.serialization.annotations.simpl_composite_as_scalar; import ecologylab.serialization.annotations.simpl_inherit; import ecologylab.serialization.annotations.simpl_scalar; import ecologylab.serialization.annotations.simpl_tag; import ecologylab.serialization.types.ScalarType; /** * A scalar field. * * @author quyin */ @SuppressWarnings("rawtypes") @simpl_inherit @simpl_tag("scalar") public class MetaMetadataScalarField extends MetaMetadataField { @simpl_scalar private MetadataScalarType scalarType; @simpl_scalar private Hint hint; @simpl_collection("value") private List<MetaMetadataValueField> concatenateValues; private List<MetaMetadataValueField> cachedValueDependencies; @simpl_scalar @simpl_tag("as_composite_scalar") private boolean compositeScalar; /** * for caching getMetaMetadataParser(). */ private String metaMetadataParser; /** * for caching getTypeNameInJava(). */ private String typeNameInJava; /** * for caching getScalarTypeInJava(). */ private String scalarTypeInJava; public MetaMetadataScalarField() { // no op } public ScalarType getScalarType() { return scalarType; } public Hint getHint() { return hint; } public void setHint(Hint hint) { this.hint = hint; } public List<MetaMetadataValueField> getConcatenateValues() { return concatenateValues; } protected void setConcatenateValues(List<MetaMetadataValueField> list) { this.concatenateValues = list; } public Boolean hasConcatenateValues() { return (this.concatenateValues != null && this.concatenateValues.size() > 0); } public Boolean hasValueDependencies() { Boolean hasDependencies = (this.getValueDependencies().size() > 0); return hasDependencies; } public List<MetaMetadataValueField> getValueDependencies() { if (cachedValueDependencies == null) { List<MetaMetadataValueField> ourDependencies = new ArrayList<MetaMetadataValueField>(); // TODO refactor to Google Guava predicates if (hasConcatenateValues()) { for (MetaMetadataValueField field : getConcatenateValues()) { if (field.fromScalar != null) { ourDependencies.add(field); } } } // More semantics that generate dep's should be filtered here... this.cachedValueDependencies = ourDependencies; return ourDependencies; } else { return cachedValueDependencies; } } public boolean isCompositeScalar() { return compositeScalar; } /** * get the parser attribute of the meta_metadata this field resides in. * * @return */ private String getMetaMetadataParser() { if (metaMetadataParser == null) { synchronized (this) { MetaMetadataField field = this; while (!(field instanceof MetaMetadata)) { field = (MetaMetadataField) field.parent(); } MetaMetadata mmd = (MetaMetadata) field; metaMetadataParser = mmd.getParser(); if (metaMetadataParser == null && mmd.getExtendsAttribute() != null) { // might be inherited from base class // TODO ... what to do ... } if (metaMetadataParser == null) { // if still null we just return an empty string to prevent null pointer exception metaMetadataParser = ""; } } } return metaMetadataParser; } @Override protected String getTypeName() { throw new RuntimeException("no mmd name for scalar fields!"); } @Override public void addAdditionalMetaInformation(List<MetaInformation> metaInfoBuf, MmdCompilerService compiler) { // @simpl_composite_as_scalar if (this.compositeScalar) metaInfoBuf.add(new MetaInformation(simpl_composite_as_scalar.class)); // FIXME Field operations, e.g. regex matching & replacing, should be done above the simpl layer // List<FieldOp> fieldOps = getFieldOps(); // if (fieldOps != null && fieldOps.size() > 0) // { // FieldOp op = fieldOps.get(0); // if (op instanceof RegexOp) // { // // @simpl_filter // RegexOp filter = (RegexOp) op; // if (filter != null && filter.getRegex() != null // && filter.getRegex().pattern().length() > 0 // && getMetaMetadataParser().equals(ParserBase.DIRECT_BINDING_PARSER)) // { // List<String> argNames = new ArrayList<String>(); // List<Object> argValues = new ArrayList<Object>(); // argNames.add("regex"); // argValues.add(filter.getJavaRegex()); // if (filter.getGroup() > 0) // { // argNames.add("group"); // argValues.add(filter.getGroup()); // } // if (filter.getReplace() != null) // { // argNames.add("replace"); // argValues.add(filter.getReplace()); // } // metaInfoBuf.add(new MetaInformation(simpl_filter.class, // argNames.toArray(new String[] {}), // argValues.toArray())); // } // } // } } @Override public String getTypeNameInJava() { String rst = typeNameInJava; if (rst == null) { rst = "Metadata" + getScalarTypeInJava(); typeNameInJava = rst; } return typeNameInJava; } private String getScalarTypeInJava() { String rst = scalarTypeInJava; if (rst == null) { if (scalarType == null) { throw new MetaMetadataException("Scalar type not defined: " + this); } rst = scalarType.fieldTypeName(); if (rst.equals("int")) { // HACK FOR METADATAINTEGER rst = "Integer"; } if (rst.equals("float")) { rst = "Float"; } scalarTypeInJava = rst; } return scalarTypeInJava; } @Override public MetadataFieldDescriptor findOrGenerateMetadataFieldDescriptor(SimplTypesScope tscope, MetadataClassDescriptor contextCd) { MetadataFieldDescriptor fd = this.getMetadataFieldDescriptor(); if (fd == null) { String tagName = this.resolveTag(); String fieldName = this.getFieldNameInJava(false); if (scalarType == null) { error("scalar_type not specified or defined: " + this); } else { String javaTypeName = scalarType.getJavaTypeName(); fd = new MetadataFieldDescriptor(this, tagName, this.getComment(), FieldType.SCALAR, null, contextCd, fieldName, scalarType, this.getHint(), javaTypeName); this.setMetadataFieldDescriptor(fd); } } return fd; } @Override protected String getFingerprintString() { StringBuilder sb = StringBuilderUtils.acquire(); sb.append(super.getFingerprintString()); addToFp(sb, scalarType); addToFp(sb, compositeScalar); addCollectionToFp(sb, concatenateValues); String fp = sb.toString(); StringBuilderUtils.release(sb); return fp; } }