All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.daisy.pipeline.css.sass.impl.SassVariable Maven / Gradle / Ivy

There is a newer version: 5.3.1
Show newest version
package org.daisy.pipeline.css.sass.impl;

import java.util.regex.Pattern;

import com.google.common.base.CaseFormat;

import org.daisy.pipeline.css.CssAnalyzer;
import org.daisy.pipeline.datatypes.DatatypeRegistry;
import org.daisy.pipeline.datatypes.DatatypeService;
import org.daisy.pipeline.datatypes.XMLBasedDatatypeService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.unbescape.css.CssEscape;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

class SassVariable implements CssAnalyzer.SassVariable {

	private final static Logger logger = LoggerFactory.getLogger(SassVariable.class.getName());

	private final String name;
	private final String nicename;
	private final String description;
	private final String value;
	private boolean isDefault = true;
	private final DatatypeService type;

	/**
	 * Create a fixed variable.
	 */
	SassVariable(String name, String value) {
		this(name, null, value, null);
		isDefault = false;
	}

	/**
	 * Create a writable variable (with a {@code !default} suffix).
	 */
	SassVariable(String name, Comment precedingComment, String defaultValue, DatatypeRegistry datatypes) {
		this.name = name;
		DoxygenComment doxygenComment; {
			doxygenComment = null;
			if (precedingComment != null && precedingComment.text.startsWith("*"))
				try {
					doxygenComment = DoxygenComment.of(precedingComment);
				} catch (IllegalArgumentException e) {
					logger.warn("Expected a Doxygen comment but got: " + precedingComment, e);
				}
		}
		String nicename = null;
		String description = "";
		DatatypeService type = null; {
			if (doxygenComment != null) {
				if (doxygenComment.varName.isPresent() && !doxygenComment.varName.get().equals(name))
					logger.warn("Declaration of variable $" + name + " was preceded by a Doxygen comment " +
					            "describing a different variable: " + precedingComment);
				else {
					nicename = doxygenComment.brief.orElse(null);
					description = doxygenComment.body;
					if (doxygenComment.type.isPresent()) {
						String t = doxygenComment.type.get();
						if ("xs:string".equals(t) || "string".equals(t))
							type = DatatypeService.XS_STRING;
						else if ("xs:integer".equals(t) || "integer".equals(t))
							type = DatatypeService.XS_INTEGER;
						else if ("xs:nonNegativeInteger".equals(t) || "nonNegativeInteger".equals(t))
							type = DatatypeService.XS_NON_NEGATIVE_INTEGER;
						else if ("xs:boolean".equals(t) || "boolean".equals(t))
							type = DatatypeService.XS_BOOLEAN;
						else if ("xs:anyURI".equals(t) || "anyURI".equals(t))
							type = DatatypeService.XS_ANY_URI;
						else if ("anyFileURI".equals(t))
							type = DatatypeService.ANY_FILE_URI;
						else if ("anyDirURI".equals(t))
							type = DatatypeService.ANY_DIR_URI;
						else {
							type = datatypes != null ? datatypes.getDatatype(t).orNull() : null;
							if (type == null)
								try {
									throw new IllegalArgumentException(
										"Invalid type in variable declaration '" + type + "': does not match a known data type");
								} catch (IllegalArgumentException e) {
									logger.warn("Invalid type in Doxygen comment: " + precedingComment, e);
								}
						}
					} else if (doxygenComment.typeDef.isPresent()) {
						Element def = doxygenComment.typeDef.get();
						type = new XMLBasedDatatypeService() { // id will be filled in later by DatatypeRegistry
							@Override
							protected Node readDocument() throws Exception {
								return def;
							}
						};
						try {
							// check if type declaration is valid
							type.validate("x"); // readTypeDecl() called lazily
						} catch (RuntimeException e) {
							type = null;
							logger.warn("Invalid type declaration in Doxygen comment: " + precedingComment, e);
						}
						if (type != null && datatypes != null)
							datatypes.registerVolatile(type);
					}
				}
			} else if (precedingComment != null)
				description = Pattern.compile("^\\s*\\*", Pattern.MULTILINE)
				                     .matcher(precedingComment.text)
				                     .replaceAll("")
				                     .replaceAll("\\s+", " ")
				                     .trim();
		}
		if (nicename == null)
			nicename = name.substring(0, 1).toUpperCase()
				+ CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name)
				                         .replace('_', ' ')
				                         .replace('-', ' ')
				                         .toLowerCase()
				                         .substring(1);
		if (type == null) {
			// infer from default value
			if ("true".equals(defaultValue) || "false".equals(defaultValue))
				type = DatatypeService.XS_BOOLEAN;
			else {
				try {
					Integer.parseInt(defaultValue);
					type = DatatypeService.XS_INTEGER;
				} catch (NumberFormatException e) {
					type = DatatypeService.XS_STRING;
				}
			}
		}
		if (type == DatatypeService.XS_STRING) {
			if (defaultValue.startsWith("\"") || defaultValue.startsWith("'")) {
				if ((defaultValue.startsWith("\"") && !defaultValue.endsWith("\""))
				    || (defaultValue.startsWith("'") && !defaultValue.endsWith("'")))
					throw new IllegalArgumentException("Invalid value in variable declaration: " + defaultValue);
				defaultValue = CssEscape.unescapeCss(defaultValue.substring(1, defaultValue.length() - 1));
			}
		}
		this.nicename = nicename;
		this.description = description;
		this.value = defaultValue;
		this.type = type;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String getNiceName() {
		return nicename;
	}

	@Override
	public String getDescription() {
		return description;
	}

	@Override
	public String getValue() {
		return value;
	}

	@Override
	public boolean isDefault() {
		return isDefault;
	}

	@Override
	public DatatypeService getType() {
		return type;
	}

	@Override
	public String toString() {
		return "$" + name + ": " + value + (isDefault ? " !default" : "") + ";";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy